I'm having an issue with getting my vector to return with data. I'm passing in a vector to getAudioStreams that'll hold the data I want, but when I print out the values, they're all empty. In getAudioStreams, I have a pointer for an array of the values, but after each loop the value in the vector becomes NULL.
I'm pretty sure this is an issue of scope, but I'm not sure how to resolve it.
Thanks for any help!
Main.cpp
std::vector<WCHAR*> names;
mvc.getAudioStreams(names);
for (int i = 0; i < names.size(); i++)
{
printf("Main I: %d | %ls\n", i, names.at(i));
}
MainVolumeControl.cpp
void MainVolumeControl::getAudioStreams(std::vector<WCHAR*>& o_streams)
{
...
WCHAR* progName;
int nSessionCount = 5;
for (int n = 0; n < nSessionCount; n++)
{
...
WCHAR wsImageName[MAX_PATH + 1];
DWORD nSize = MAX_PATH;
if (QueryFullProcessImageNameW(hProcess, NULL, wsImageName, &nSize))
{
printf("\nImage: %ls\n", wsImageName);
progName = extractName(wsImageName);
printf("Prog: %ls\n\0", progName);
o_streams.push_back(progName);
}
...
}
...
printf("\n");
for (int i = 0; i < o_streams.size(); i++)
{
printf("I: %d | %ls\n", i, o_streams.at(i));
printf("\n");
}
}
WCHAR* MainVolumeControl::extractName(WCHAR i_imageName[])
{
constexpr u_int LEN_IMAGE_MAX = MAX_PATH + 1;
WCHAR o_progName[LEN_IMAGE_MAX];
... // Extracting the name from a longer string
return o_progName;
}
Thank you #JaMit & #Richard Critten!
Returning a value instead of using pointers/references solved the issue.
Using std::wstring instead of WCHAR* cleaned up my code a decent bit too
Related
I've been running into this weird issue where the split code returns correctly when I printf output inside the function, but will incorrectly return output upon calling it as an instance.
Question: How do I get the correct ouput when calling it as an instance?(see useage bellow)
Here is the code:
typedef struct SplitText
{
int splitLen;
char* splitTxt[100];
char* subTxt(char* text, int index, int len)
{
char subTxt_[1000];
int count = 0;
for (int i = 0; i < 1000; i++)
subTxt_[i] = '\0';
for (int i = index; i < index + len; i++)
subTxt_[count++] = text[i];
return subTxt_;
}
void split(char* text, char sep)
{
char separator[3] = { '<', sep, '>' };
int textLen = strlen(text);
int splitIndex = 0;
int splitCount = 0;
for (int t = 0; t < textLen; t++)
{
if (text[t] == separator[0] && text[t + 1] == separator[1] && text[t + 2] == separator[2])
{
if (splitIndex != 0)
splitIndex += 3;
splitTxt[splitCount] = subTxt(text, splitIndex, t - splitIndex);
splitIndex = t;
//correct output
printf(splitTxt[splitCount]);
printf("\n");
splitCount++;
}
}
splitLen = splitCount;
}
}SplitText;
Useage:
SplitText st;
st.split("testing<=>split<=>function<=>", '=');
for (int i = 0; i < st.splitLen; i++)
{
//incorrect output
printf(st.splitTxt[i]);
printf("\n");
}
printf("--------\n");
This:
char* subTxt(char* text, int index, int len)
{
char subTxt_[1000];
...
return subTxt_;
}
Is undefined behavior. Returning a pointer to a local stack variable (or local array var) is going to result in weird stuff like this happening.
The typical thing that corrupts the contens of that returned pointer is when another function is invoked, the memory occupied by subTxt_ is going to get overwritten with the stack variables of the next function invoked.
Better:
char* subTxt(char* text, int index, int len)
{
char *subTxt = new char[1000];
...
return subTxt_;
}
And then make sure whoever invokes subTxt remembers to delete [] on the returned pointer.
Or just use std::string and be done with it (unless this is an academic exercise).
Also, this is undefined behavior:
for (int t = 0; t < textLen; t++)
{
if (text[t] == separator[0] && text[t + 1] == separator[1] && text[t + 2] == separator[2])
when t == textLen-1, then referencing text[t+2] and text[t+1] is an out of bounds access. Change it to be:
for (int t = 2; t < textLen; t++)
{
if (text[t-2] == separator[0] && text[t -1] == separator[1] && text[t] == separator[2])
And do similar fixups with t within the block as well.
Well you can create a splitstring function instead of a struct/class.
Anyway your code still looks quite "C" like with its fixed size char arrays. This will limit the usability and stability (out-of-bound array bugs).
Strings in C++ are usually of type std::string.
and then C++ has string_view to make views on that string (so no data gets copied, but it also means your string_view is only valid for as long as the string it is viewing lives).
If you don't know the number of substrings in a string up-front, you should not use a fixed size array, but a std::vector (which can resize internally if needed)
This is what a split_string function would look like in current C++, note that the code also shows better what it is doing compared to "C" style programming that show more what you are doing.
std::vector<std::string_view> split_string(std::string_view string, std::string_view delimiters)
{
std::vector<std::string_view> substrings;
if(delimiters.size() == 0ul)
{
substrings.emplace_back(string);
return substrings;
}
auto start_pos = string.find_first_not_of(delimiters);
auto end_pos = start_pos;
auto max_length = string.length();
while(start_pos < max_length)
{
end_pos = std::min(max_length, string.find_first_of(delimiters, start_pos));
if(end_pos != start_pos)
{
substrings.emplace_back(&string[start_pos], end_pos - start_pos);
start_pos = string.find_first_not_of(delimiters, end_pos);
}
}
return substrings;
}
Take a look at std::string_view.
You can avoid allocating memory and it has a built-in substring function.
Just be careful when using printf for printing to console as "%s" will
print the whole string.
See printf documentation.
for(auto view : container_with_string_views)
printf("%.*s, (int)view.size(), view.data());
I understand PBYTE is unsigned char* from Windows Data Types.
I am calling a function which updates data and dataSize.
I print the data after I call the function, but once I print the vector that stores all the data, I am not getting the same value.
Is it possible that the data is getting corrupted?
This is a function written internally, not open-source.
SerializeEvent(__in_z PCWSTR EventName,
__out_bcount(DataSize) PBYTE & Data,
__out ULONG & DataSize){}
This function takes in a field and serializes it and data is basically the buffer where the serialize event name is stored, and dataSize is the size for the same.
PBYTE data=NULL;
ULONG dataSize=0;
int main(){
vector<PBYTE> dataVector;
vector<ULONG> dataSizeVector;
for(int i=0;i<10;i++){
serializeData(event,data,dataSize);
printf("%02x ",data); ///----->a
dataVector.push_back(data);
dataSizeVector.push_back(dataSize);
}
//just want to print the contents of this vector to verify
for(int i=0;i<dataVector.size();i++){
printf("%02x ",dataVector.at(i)); ----> b
}
}
The print from the first for loop is not matching the print from the second for loop. Am I missing something?
But doing the same for dataSizeVector is printing similar values...
Both loops are printing out incorrect data.
printf("%02x ", ...); is being given a BYTE* pointer as the input value for %x, but %x expects an integer not a pointer.
As I already showed you in your previous question, you can print out individual bytes using %x, and print out pointers using %p instead.
Try something more like this:
int main() {
vector<PBYTE> dataVector;
vector<ULONG> dataSizeVector;
for(int i = 0; i < 10; ++i) {
PBYTE data = NULL;
ULONG dataSize = 0;
SerializeEvent(event, data, dataSize);
printf("%p", data);
for(ULONG j = 0; j < dataSize; ++j) {
printf(" %02x", data[j]);
}
printf("\n");
dataVector.push_back(data);
dataSizeVector.push_back(dataSize);
}
//just want to print the contents of this vector to verify
for(size_t i = 0; i < dataVector.size(); ++i) {
PBYTE data = dataVector[i];
ULONG dataSize = dataSizeVector[i];
printf("%p", data);
for(ULONG j = 0; j < dataSize; ++j) {
printf(" %02x", data[j]);
}
printf("\n");
}
}
I suggest you read this printf() reference on how printf() actually works.
I'm trying to initialize an array of integers dynamically, since the size of the array changes based on input.
The program is as follows:
int main()
{
int* list = createList("dis.bin");
for (int i = 0; i < sizeof(list) / sizeof(int); i++)
{
printf("%d\n", list[i]);
}
}
With createList() function as written:
int* createList(const char* file_name)
{
int counter = 1;
int* inst{};
FILE* myFile = fopen(file_name, "rb");
if (myFile == nullptr)
{
printf("\nFile not opened\n");
return 0;
}
int x = 0;
for (int i = 0; !(feof(myFile)); i++)
{
fread(&x, sizeof(int), 1, myFile);
inst = new int[counter];
inst[i] = x;
printf("%08x #%-4d | Int equiv: %-12d | Bin equiv: %s\n", x, counter, inst[i], ToBinary(inst[i], 0));
counter += 1;
x = 0;
}
return inst;
}
createList reads from a .bin file (basically containing an array of bytes) and inserts each pair of 4 bytes to an item in the array inst. I do this by allocating a new amount of space for the array based on the counter variable. (So whatever value counter is becomes the size of the array with inst = new int[counter]) Then I set the contents of the array at the given index i equal to x (the pair of bytes read) I would assume it is working correctly in createList at least, because of the printf statement which is printing each element in inst[].
However, when I call createList("dis.bin") in main and assign it to the variable int* list, I try to iterate through each value. But this just prints out one uninitialized value (-842150451, if you're curious). So I'm not sure what I'm doing wrong here?
I should mention that I am NOT using vectors or really any std container. I am just working with arrays. I also am using printf for specific reasons.
This question is tagged as C++, but OP is showing C code and says they need it in C, so I will show this in C... but the pre-req is that it uses new and not malloc
int* createList(const char* file_name, int& count)
{
// initialize count, so that way if we return early, we don't have invalid information
count = 0;
// open the file ad "READ" and "BINARY"
FILE* myFile = fopen(file_name, "rb");
if (!myFile)
{
printf("\nFile not opened\n");
return 0;
}
// calculate how many 4-byte integers exist in the file using
// the file length
fseek(myFile, 0, SEEK_END);
count = ftell(myFile) / sizeof(int);
rewind(myFile);
// allocate the memory
int* returnData = new int[count];
// read in 4-byte chunks to our array until it can't read anymore
int i = 0;
while (fread(&returnData[i++], sizeof(int), 1, myFile) == 1);
// close the file
fclose(myFile);
// return our newly allocated data
return returnData;
}
int main()
{
int count;
int* myInts = createList("c:\\users\\andy\\desktop\\dis.bin", count);
for (int i = 0; i < count; ++i) {
printf("%d\n", myInts[i]);
}
// don't forget to delete your data. (another reason a vector would be better suited... no one remembers to delete :)
delete myInts;
}
Two things here:
The usage of new was misinterpreted by me. For whatever reason, I thought that each time I allocated new memory for inst that it would just be appending new memory to the already allocated memory, but this is obviously not the case. If I wanted to simulate this, I would have to copy the contents of the array after each iteration and add that to the newly allocated memory. To solve this, I waited to allocate memory for inst until after the file iteration was complete.
As Andy pointed out, sizeof(list) / sizeof(int) would not give me the number of elements in list, since it is a pointer. To get around this, I created a new parameter int &read for the createList() function in order to pass the number of items created.
With these points, the new function looks like this and works as intended:
int* createList(const char* file_name, int &read)
{
int counter = 1;
FILE* myFile = fopen(file_name, "rb");
if (myFile == nullptr)
{
printf("\nFile not opened\n");
return 0;
}
int x = 0;
for (int i = 0; !(feof(myFile)); i++)
{
fread(&x, sizeof(int), 1, myFile);
printf("%08x #%-4d | Int equiv: %-12d | Bin equiv: %s\n", x, counter, x, ToBinary(x, 0));
counter += 1;
}
int* inst = new int[counter];
read = counter;
rewind(myFile); // rewind to beginning of file
for (int i = 0; !(feof(myFile)); i++)
{
fread(&x, sizeof(int), 1, myFile);
inst[i] = x;
x = 0;
}
return inst;
}
With main changed a bit as well:
int main()
{
int read;
int* list = createList("dis.bin", read);
for (int i = 0; i < read; i++)
{
printf("%d\n", list[i]);
}
}
As for the comments about the invalidity of !(feof(myFile)), although helpful, this was not a part of my question and thus not of my concern. But I will source the solution to that for the sake of spreading important information: Why is "while ( !feof(file) )" always wrong?
I am trying to resize a vector element of a structure and it causes segv. But when I did it individually for some small struct it worked fine. I am curious to know how it allocates memory to structure in which there is a vector element that could be resized. The below comment line causes segv in first iteration (type_index = 0).
Structure:-
struct thread_data {
dbPointer_t pObj;
dbObjId_t objId;
dbObjTypeId_t type;
dbObjId_t topCellId;
dbIteratorId_t objsIterId;
int precision;
int64_t shape_objs;
vector<vector<vector<PL_trp_header_t *> > > ps_hdrs;
int pool;
int num_layers;
int to_cell_id;
};
Below is the snippet of code:-
thread_data *t_data[types_length];
for(int type_index=0; type_index < types_length; ++type_index) {
t_data[type_index] = (thread_data*)malloc(sizeof(thread_data));
t_data[type_index]->pObj = NULL;
t_data[type_index]->objId = objId;
t_data[type_index]->type = shape_types[type_index];
t_data[type_index]->topCellId = topCellId;
t_data[type_index]->objsIterId = objsIterId;
t_data[type_index]->precision = nparams.unit_precision;
t_data[type_index]->shape_objs = 0;
t_data[type_index]->ps_hdrs.resize(num_layers); //this line causes segv
t_data[type_index]->pool = pool;
t_data[type_index]->num_layers = num_layers;
t_data[type_index]->to_cell_id = tocell_id;
for (int num = 0; num < num_layers; num++) {
t_data[type_index]->ps_hdrs[num].resize(index_limit);
for (int rows = 0; rows < index_limit; rows++)
t_data[type_index]->ps_hdrs[num][rows].resize(index_limit);
}
for(int i = 0; i < num_layers; i++) {
for (int rows = 0; rows < index_limit; rows++) {
for (int cols = 0; cols < index_limit; cols++) {
t_data[type_index]->ps_hdrs[i][rows][cols] = alloc_hdr(pool);
}
}
}
printf("In main: creating thread %d \n", type_index);
rc_thread = pthread_create(&threads[type_index], NULL, thread_fn, (void *) &t_data[type_index]);
if (rc_thread){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
free(t_data[type_index]);
}
I think you are allocating your data with malloc. In this case no constructors for your objects and theier members are called. This works with PODs but not with classes like vector. In the line with the error you try to access some unitialised memory like an vector. Try new and delete instead of mallac and free to solve this isue.
I'm trying to copy data from an array of character that send from main to another one in my local function and I always see garbage characters even though I've add '\0' at the end of the string.
Here is my partial of the code.
for (int i = 0; i < strlen(main) ; i++){
if (main[i] != ';'){
local[i] = main[i]; // Copy the characters until `;` isn't found
} else {
local[i] = '\0' ; // If `;` found, null terminate the copied destination.
break;
}
}
so basically the data that being send from main for example like this
look;can;you;see;me
My Local-----> 'look??y??>c?Lw?T?w??>c?2+a?'
Actual data in main---> 'look'
As you can see from the above example I'm trying to get only the first word and I always get garbage I don't know why?
EDIT:
This is the almost the whole function which 100% sure that is causing me the problem.
void myFunction(char main[ ]){
for (int i = 0; i < strlen(main) ; i++){
if (main[i] != ';'){
local[i] = main[i]; // Copy the characters until `;` isn't found
} else {
local[i] = '\0' ; // If `;` found, null terminate the copied destination.
break;
}
}
if(main[i] != '\0'){
int col = 0, row = 0;
do {
if(main[i] == ';' || main[i] == '\0') {
sending[row++][col] = '\0';
col = 0;
} else {
sending[row][col++] = main[i];
}
} while(main[i++] != '\0');
}
}
You are forgetting to take care of zero terminating the string if the ; is not found. A simple fix is tweaking your for loop so it also sees the \0 in main:
for (int i = 0; i <= strlen(main); i++) {
The standard library handles this for you. Using strchr and strncpy:
size_t length = std::strlen(main);
const char* current_pos = main;
for (int i = 0; ; ++i) {
size_t chars_remaining = length - std::distance(main, current_pos);
const char* end_of_field = std::strchr(current_pos, ';');
if (end_of_field == NULL) {
std::strncpy(local[i], current_pos, chars_remaining + 1);
// we're at the end of the input
break;
}
else {
size_t field_length = std::distance(current_pos, end_of_field);
std::strncpy(local[i], current_pos, field_length);
// don't forget to NUL-terminate the string
local[i][field_length] = '\0';
// go to next character for the next iteration through loop
current_pos = end_of_field + 1;
}
}
Personally, I prefer std::find and std::copy (from <algorithm>):
size_t length = std::strlen(main);
const char* current_pos = main;
for (int i = 0; ; ++i) {
size_t chars_remaining = length - std::distance(main, current_pos);
const char* end_of_field = std::find(current_pos, current_pos + chars_remaining, ';');
char* output_end = std::copy(current_pos, end_of_field, local[i]);
// don't forget to NUL-terminate the string
*output_end = '\0';
// if we're at the end of main, then we're done;
// we're at the end if we're on a NUL character
if (*end_of_field == '\0')
break;
// go to next character for the next iteration through loop
current_pos = end_of_field + 1;
}
Not the prettiest code I've ever written, but that's largely due to using C-style strings and pointer arithmetic, which don't look avoidable given the original question. Additionally, I haven't put in the needed checks for overflow. It's easy enough to do that, but it's even easier to use std::vector<std::string> and have the standard library worry about that for you.