ostringstream gets wrong int value after incrementation [c++] - c++

This is part of my code:
for(int i=0; i<10; i++)
{
tab[i]=new char[80];
oss.str("");
oss<<"line number: <<i;
temp=oss.str();
tab[i]=(char*)temp.c_str();
}
and when I print the tab, the result is in turns 8 and 9. Am I doing something wrong?

Taking a bunch of comments and consolidating (Why are you commentators not answering instead?):
What you are actually doing there is changing the pointer value of tab[i] from your allocated memory to the internal string of temp. Which is a bad idea because temp will free that memory as soon as it is destructed.
You don't need temp at all, as far as I can see.
The C way to fix this is to use strcpy(tab[i], oss.str().c_str()) which will copy the characters one by one. Note that your current code does a new char[80] so if your string is longer than 79 characters it will overflow. If you must use a new'd buffer, do it with something like new char[oss.str().size() + 1]
The C++ way to fix this is to use an array of std::string instead of an array of char*. Then you could just assign, like tab[i] = oss.str() and it would copy it properly. It would also clean up the memory used when the array goes out of scope, as your code right now doesn't do.

Related

Getting sementation fault (core dumped)

Everything seems to run okay up until the return part of shuffle_array(), but I'm not sure what.
int * shuffle_array(int initialArray[], int userSize)
{
// Variables
int shuffledArray[userSize]; // Create new array for shuffled
srand(time(0));
for (int i = 0; i < userSize; i++) // Copy initial array into new array
{
shuffledArray[i] = initialArray[i];
}
for(int i = userSize - 1; i > 0; i--)
{
int randomPosition = (rand() % userSize;
temp = shuffledArray[i];
shuffledArray[i] = shuffledArray[randomPosition];
shuffledArray[randomPosition] = temp;
}
cout << "The numbers in the initial array are: ";
for (int i = 0; i < userSize; i++)
{
cout << initialArray[i] << " ";
}
cout << endl;
cout << "The numbers in the shuffled array are: ";
for (int i = 0; i < userSize; i++)
{
cout << shuffledArray[i] << " ";
}
cout << endl;
return shuffledArray;
}
Sorry if spacing is off here, not sure how to copy and past code into here, so I had to do it by hand.
EDIT: Should also mention that this is just a fraction of code, not the whole project I'm working on.
There are several issues of varying severity, and here's my best attempt at flagging them:
int shuffledArray[userSize];
This array has a variable length. I don't think that it's as bad as other users point out, but you should know that this isn't allowed by the C++ standard, so you can't expect it to work on every compiler that you try (GCC and Clang will let you do it, but MSVC won't, for instance).
srand(time(0));
This is most likely outside the scope of your assignment (you've probably been told "use rand/srand" as a simplification), but rand is actually a terrible random number generator compared to what else the C++ language offers. It is rather slow, it repeats quickly (calling rand() in sequence will eventually start returning the same sequence that it did before), it is easy to predict based on just a few samples, and it is not uniform (some values have a much higher probability of being returned than others). If you pursue C++, you should look into the <random> header (and, realistically, how to use it, because it's unfortunately not a shining example of simplicity).
Additionally, seeding with time(0) will give you sequences that change only once per second. This means that if you call shuffle_array twice quickly in succession, you're likely to get the same "random" order. (This is one reason that often people will call srand once, in main, instead.)
for(int i = userSize - 1; i > 0; i--)
By iterating to i > 0, you will never enter the loop with i == 0. This means that there's a chance that you'll never swap the zeroth element. (It could still be swapped by another iteration, depending on your luck, but this is clearly a bug.)
int randomPosition = (rand() % userSize);
You should know that this is biased: because the maximum value of rand() is likely not divisible by userSize, you are marginally more likely to get small values than large values. You can probably just read up the explanation and move on for the purposes of your assignment.
return shuffledArray;
This is a hard error: it is never legal to return storage that was allocated for a function. In this case, the memory for shuffledArray is allocated automatically at the beginning at the function, and importantly, it is deallocated automatically at the end: this means that your program will reuse it for other purposes. Reading from it is likely to return values that have been overwritten by some code, and writing to it is likely to overwrite memory that is currently used by other code, which can have catastrophic consequences.
Of course, I'm writing all of this assuming that you use the result of shuffle_array. If you don't use it, you should just not return it (although in this case, it's unlikely to be the reason that your program crashes).
Inside a function, it's fine to pass a pointer to automatic storage to another function, but it's never okay to return that. If you can't use std::vector (which is the best option here, IMO), you have three other options:
have shuffle_array accept a shuffledArray[] that is the same size as initialArray already, and return nothing;
have shuffle_array modify initialArray instead (the shuffling algorithm that you are using is in-place, meaning that you'll get correct results even if you don't copy the original input)
dynamically allocate the memory for shuffledArray using new, which will prevent it from being automatically reclaimed at the end of the function.
Option 3 requires you to use manual memory management, which is generally frowned upon these days. I think that option 1 or 2 are best. Option 1 would look like this:
void shuffle_array(int initialArray[], int shuffledArray[], int userSize) { ... }
where userSize is the size of both initialArray and shuffledArray. In this scenario, the caller needs to own the storage for shuffledArray.
You should NOT return a pointer to local variable. After the function returns, shuffledArray gets deallocated and you're left with a dangling pointer.
You cannot return a local array. The local array's memory is released when you return (did the compiler warn you about that). If you do not want to use std::vector then create yr result array using new
int *shuffledArray = new int[userSize];
your caller will have to delete[] it (not true with std::vector)
When you define any non static variables inside a function, those variables will reside in function's stack. Once you return from function, the function's stack is gone. In your program, you are trying to return a local array which will be gone once control is outside of shuffle_array().
To solve this, either you need to define the array globally (which I won't prefer because using global variables are dangerous) or use dynamic memory allocation for the array which will create space for the array in heap rather than allocating the space on the function's stack. You can use std::vectors also, if you are familiar with vectors.
To allocate memory dynamically, you have to use new as mentioned below.
int *shuffledArray[] = new int[userSize];
and once you completed using shuffledArray, you need to free the memory as below.
delete [] shuffledArray;
otherwise your program will leak memory.

delete[] causing heap corruption

I'm well aware that there are countless problems like this, but I searched for hours and couldn't understand what I did wrong so I would really appreciate your help. (I'm new to programming)
I need to create a dictionary manager of sorts as part of my homework but I seem to have a problem with deleting words.
I get an error message "...triggered a breakpoint".
The usual answer people get to this problem is that this is heap corruption caused by going out of bounds but I can't see if and how I caused this.
I already made something similar with bus info management and it worked perfectly so that makes me even more confused... (Obviously, I did not make the mechanism exactly the same, but even after looking at my previous code I couldn't isolate the problem)
I added the functions I believe are of concern,
The adding function:
void Add_Word(char**& dictionary, int& dictionary_size, char word[])
{
char** temp = new char*[dictionary_size + 1]; // Create a new array of appropriate size.
int i;
for (i = 0; i < dictionary_size; i++)
{
temp[i] = dictionary[i]; // Copy head pointers addresses for all existing items.
}
temp[i] = new char[strlen(word)]; // Add the space for the new word,
temp[i][strlen(word)] = '\0'; // mark its end
strcpy_s(temp[i], strlen(word) + 1, word); // then copy it.
// I'm really not so sure about what I should put in the buffer length but
// strlen(word) + 1 seemed to work... I know... not good, but strlen(word) alone caused a problem.
if (dictionary_size > 0)
delete []dictionary; // Delete previous head pointers array if there are any and
dictionary = temp; // reset the main pointer to the address of the new one.
dictionary_size++; // Finally, increase dictionary_size.
}
The deleting function:
void Delete_Word(char**& dictionary, int& dictionary_size, char* word)
{
// !!! This is where the crash thingy happens.
delete[] Search_For_Word(dictionary, dictionary_size, word); // Delete the word from the dictionary.
// Search_For_Word returns a pointer to the word it receives, from the dictionary.
char** temp = new char*[dictionary_size - 1]; // Create a new array of appropriate size.
int i;
for (i = 0; i < dictionary_size; i++)
{
if (dictionary[i][0])
temp[i] = dictionary[i]; // Copy the head pointers of the existing
// items to the new array except for the deleted word.
}
delete[] dictionary; // Delete previous head pointers array and
dictionary = temp; // reset the main pointer to the address of the new one.
dictionary_size--; // Finally, decrease dictionary_size.
}
EDIT: Any parts that are excessively inefficient or obviously broken are likely a result of me messing with my code trying to figure this out on my own (such as the calling 3 times to strlen mentioned (thanks again for that, kfsone...), or forgetting to +1 it for the '\0' to mark the end of a string
--actually, no, if we go by obvious you won't tell me my mistakes #.#).
As for the reason I'm dealing with char instead of strings and vectors please allow me to quote myself: "...as part of my homework". I just barely started programming. That, and I want to grasp the basics before moving on to using the more comfortable higher-up tools.
Change:
temp[i] = new char[strlen(word)]
To:
temp[i] = new char[strlen(word)+1]
Your code has several problems.
First, if you want to allocate a C-style string on the heap using new[], then you must pay attention to the terminating NUL character.
So, if you want to do a deep copy from a string word, then you must calculate enough room, considering strlen(word) + 1: the +1 is for the terminating NUL character.
e.g.:
// Original code (wrong):
//
// temp[i] = new char[strlen(word)];
//
// New code:
temp[i] = new char[strlen(word) + 1]; // consider terminating NUL (+1)
Moreover, following your code with explicit new[]s and delete[]s is not easy.
In modern C++, you may want to use convenient robust container classes like std::vector and string classes like std::string, instead of raw C-style pointers and strings.
You can simply store a list of strings using a std::vector<std::string>, and vector::push_back() method to add new strings to the vector. No need to complicate code with new[], delete[], strcpy_s(), etc.
And if you want to deep-copy strings, you can just use the simple natural overload of operator= for std::string, and copy constructors; e.g. std::string temp = word; will work just fine.
This is C++, why are you not using std::string instead of char buffers?
If you must use char buffer strings and the secure forms of strcpy_s know that the buffer length must always be the size of the destination buffer, never a strlen function. In your case it is a bit understandable since you created the buffer with the strlen function. But what you should do is set the value into a variable and then use that any time you need the buffer size.
Also, and where I think your bug is, you are writing temp[i][strlen(word)] = '\0'; But the actual indexes of the buffer go from 0 to strlen(word)-1 so you're writing outside the allocated memory.
The code is now working.
It was wrong all over.
I messed up pretty much any part that I could regarding the dynamic memory while trying to fix it before.
I initially didn't care about calling 3 times to strlen becuase it's just homework and a very small program but I guess it's better to get used to do things the right way...
I also dropped the copy which I evidently don't understand very well in favour of a simple for loop.
// Add function. The rest is cut.
int word_length = strlen(word);
temp[i] = new char[word_length + 1]; // Added +1 here.
temp[i][word_length] = '\0'; /* This was correct after all.
the word_length index is the correct ending.*/
for (int j = 0; j < word_length; j++) // copy replaced by for loop.
temp[i][j] = word[j];
// cut
}
void Delete_Word(char**& dictionary, int& dictionary_size, char* word)
{
delete[] Search_For_Word(dictionary, dictionary_size, word);
// There was a -1 mistake here I made in order to try and fix the thing earlier.
// No need for more, it works perfectly now.

100% of array correct in function, 75% of array correct in CALLING function - C

Note: i'm using the c++ compiler, hence why I can use pass by reference
i have a strange problem, and I don't really know what's going on.
Basically, I have a text file: http://pastebin.com/mCp6K3HB
and I'm reading the contents of the text file in to an array of atoms:
typedef struct{
char * name;
char * symbol;
int atomic_number;
double atomic_weight;
int electrons;
int neutrons;
int protons;
} atom;
this is my type definition of atom.
void set_up_temp(atom (&element_record)[DIM1])
{
char temp_array[826][20];
char temp2[128][20];
int i=0;
int j=0;
int ctr=0;
FILE *f=fopen("atoms.txt","r");
for (i = 0; f && !feof(f) && i < 827; i++ )
{
fgets(temp_array[i],sizeof(temp_array[0]),f);
}
for (j = 0; j < 128; j++)
{
element_record[j].name = temp_array[ctr];
element_record[j].symbol = temp_array[ctr+1];
element_record[j].atomic_number = atol(temp_array[ctr+2]);
element_record[j].atomic_weight = atol(temp_array[ctr+3]);
element_record[j].electrons = atol(temp_array[ctr+4]);
element_record[j].neutrons = atol(temp_array[ctr+5]);
element_record[j].protons = atol(temp_array[ctr+6]);
ctr = ctr + 7;
}
//Close the file to free up memory and prevent leaks
fclose(f);
} //AT THIS POINT THE DATA IS FINE
Here is the function I'm using to read the data. When i debug this function, and let it run right up to the end, I use the debugger to check it's contents, and the array has 100% correct data, that is, all elements are what they should be relative to the text file.
http://i.imgur.com/SEq9w7Q.png This image shows what I'm talking about. On the left, all the elements, 0, up to 127, are perfect.
Then, I go down to the function I'm calling it from.
atom myAtoms[118];
set_up_temp(myAtoms); //AT THIS POINT DATA IS FINE
region current_button_pressed; // NOW IT'S BROKEN
load_font_named("arial", "cour.ttf", 20);
panel p1 = load_panel("atomicpanel.txt");
panel p2 = load_panel("NumberPanel.txt");
As soon as ANYTHING is called, after i call set_up_temp, the elements 103 to 127 of my array turn in to jibberish. As more things get called, EVEN MORE of the array turns to jibberish. This is weird, I don't know what's happening... Does anyone have any idea? Thanks.
for (j = 0; j < 128; j++)
{
element_record[j].name = temp_array[ctr];
You are storing, and then returning, pointers into temp_array, which is on the stack. The moment you return from the function, all of temp_array becomes invalid -- it's undefined behavior to dereference any of those pointers after that point. "Undefined behavior" includes the possibility that you can still read elements 0 through 102 with no trouble, but 103 through 127 turn to gibberish, as you say. You need to allocate space for these strings that will live as long as the atom object. Since as you say you are using C++, the easiest fix is to change both char * members to std::string. (If you don't want to use std::string, the second easiest fix is to use strdup, but then you have to free that memory explicitly.)
This may not be the only bug in this code, but it's probably the one causing your immediate problem.
In case you're curious, the reason the high end of the data is getting corrupted is that on most (but not all) computers, including the one you're using, the stack grows downward, i.e. from high addresses to low. Arrays, however, always index from low addresses to high. So the high end of the memory area that used to be temp_array is the part that's closest to the stack pointer in the caller, and thus most likely to be overwritten by subsequent function calls.
Casual inspection yields this:
char temp_array[826][20];
...
for (i = 0; f && !feof(f) && i < 827; i++ )
Your code potentially allows i to become 826. Which means you're accessing the 827th element of temp_array. Which is one past the end. Oops.
Additionally, you are allocating an array of 118 atoms (atom myAtoms[118];) but you are setting 128 of them inside of set_up_temp in the for (j = 0; j < 128; j++) loop.
The moral of this story: Mind your indices and since you use C++ leverage things like std::vector and std::string and avoid playing with arrays directly.
Update
As Zack pointed out, you're returning pointers to stack-allocated variables which will go away when the set_up_temp function returns. Additionally, the fgets you use doesn't do what you think it does and it's HORRIBLE code to begin with. Please read the documentation for fgets and ask yourself what your code does.
You are allocating an array with space for 118 elements but the code sets 128 of them, thus overwriting whatever happens to live right after the array.
Also as other noted you're storing in the array pointers to data that is temporary to the function (a no-no).
My suggestion is to start by reading a good book about C++ before programming because otherwise you're making your life harder for no reason. C++ is not a language in which you can hope to make serious progress by experimentation.

C++ Assignment, strcpy and strlen with character arrays n pointers

I am working on this assignment and have encountered a problem. At one point, I have to ask the user for two input commands to be used later and I want them put in a char array. I then want to put the input they have into char* but I end up with a Segmentation fault
Here is a small part of my code that shows where I'm having problems:
#include <iostream>
#include <cstring>
using namespace std;
int main(){
char firstAns[80];
char * command1[5];
int ansLen;
//Ask for command
cout << "Please enter your first command(incl. args) or quit: ";
cin >> firstAns;
ansLen = strlen(firstAns);
for(int i=0; i < ansLen; i++){
strcpy(command1[i], firstAns);
}
The program that I ran this from compiles just fine but I have narrowed the segmentation fault to this part of the program and could use some help as a novice programmer :)
You have an array of char* called command. But you haven't allocated any memory for the pointers in the array, or even set them to null. SO they're random values, pointing to random memory locations. Strcpy is then overwriting those random locations, causing a seg fault. You need to allocate memory for those pointers by command[i]=new char[80] on all 5 rows first.
char * command1[5];
This is an array of char*s. However, it is uninitialized - the values can be any value, and as such they point to random, meaningless places in memory.
You then later use the uninitialized command1[i] in strcpy(command1[i], firstAns);. Essentially, what you have done is taken a random place in memory and tried to copy firstAns to it. No wonder your program crashes!
Before using a pointer, you have to initialize it to some value. If you need storage in memory, use malloc() to return storage of the correct size (sizeof(datatype)*length +1 if it is a string) and remember to free() the pointer returned from it when you're done with it.
Read more: http://www.cplusplus.com/reference/cstdlib/malloc/
(Gabe Sechan's solution is also valid. new and malloc are the C++ and C ways of allocating memory)
Additional Problem is here:
ansLen = strlen(firstAns);
for(int i=0; i < ansLen; i++){
strcpy(command1[i], firstAns);
}
ansLen is the length of firstAns, it may be possible that it is longer than 5. In this case,
if you try to access command1[i], you are going to access memory that out of bounds, results in segfault.
Meanwhile, you are using unitialized command1 as pointed out by Patashu and Gabe.

Simple examples with 2 dimensional wchar_t string array

Can somebody explain why next code output 26 timez 'Z' instead range from 'A' to 'Z', and how can I output this array correct. Look at code:
wchar_t *allDrvs[26];
int count = 0;
for (int n=0; n<26; n++)
{
wchar_t t[] = {L'A' + n, '\0'};
allDrvs[n] = t;
count++;
}
int j;
for(j = 0; j < count; j++)
{
std::wcout << allDrvs[j] << std::endl;
}
The problem (at least one) is:
{
wchar_t t[] = {L'A' + n, '\0'};
allDrvs[n] = t; //allDrvs points to t
count++;
} //t is deallocated here
//allDrvs[n] is a dangling pointer
So, short answer - undefined behavior on the line std::wcout << allDrvs[j].
To get a correct output - there's a crappy ugly version involving dynamic allocation and copying between arrays.
Then there's the correct version of using a std::vector<std::wstring> >.
Your t[] is on the stack; it only exists for one iteration of the loop at a time, and the next iteration appears to be reusing that space - not a behaviour that's required, but this seems to be what's happening based on your results. If you examine allDrvs[] with a debugger after the first loop completes, you'll probably see all the pointers point to the same memory location.
There's a variety of ways you could solve this. You can allocate a new t on the heap for each loop iteration (and delete them afterwards). You could do wchar_t allDrvs[26][2]; instead of wchar_t *allDrvs[26], and copy the contents of t over each iteration. You could display t right away in the first loop, instead of doing it later. You could use std::vector and std::wstring to manage things for you, instead of using arrays and pointers.
Your code has undefined behavior. Your t has automatic storage duration, so as soon as you exit the upper loop, it ceases to exist. Your allDrvs contains 26 pointers to objects that have been destroyed by the time you use them in the second loop.
As it happens, it looks like (under the circumstances you're running it, with the compiler you're using, etc.) what's happening is that it's re-using the same storage space for t at ever iteration of the loop, and when you use allDrvs in the second loop, that storage hasn't been overwritten, so you have 26 pointers to the same data.
Since you're using C++ anyway, I'd advise using std::wstring and probably std::vector instead -- for example, something on this general order:
std::vector<std::wstring> allDrvs;
for (char i=L'A'; i<L'Z'; i++)
allDrvs.push_back(std::wstring(i));
Technically, this isn't entirely portable -- it depends on 'A' .. 'Z' being contiguous, which isn't true with all character sets, IBM's EBCDIC being the obvious exception. Even in that case, it'll produce all the right outputs, but it'll also include a few additional items you didn't really want.
Nonetheless, the original depended on 'A'..'Z' being contiguous, and the code looks like it's probably intended for Windows anyway, so that's probably not really a big concern.