C++ Seg Fault at end of function. Reference line = closing brace - c++

In conclusion: Thanks so much everyone! All the responses posted below were correct. The initial error was me forgetting to leave room for the NULL terminator. Strcpy() is a dangerous function because when I used it, it didn't know when the end of the 'string' was. Therefore, strcpy() grabbed to much data and overwrote the return address.
EDIT: added more code from the program
SOLVED: Honestly, my initial implementation was crap. I don't even know why I wrote swap that way if I wanted to swap out elements of the array. (At the time, each element only had the a char array in it. So I was able to get away with the old implementation). I have re-written it to:
void swap(ArrayElement list[], int index1, int index2) {
ArrayElement temp;
temp = list[index1];
list[index1] = list[index2];
list[index2] = temp;
}
I'm having problems with a segmentation fault at the end of the following function.
struct ArrayElement {
char data[SIZE_OF_ELEMENT];
// Implemented this way so that I can expand to multiple values later on
}
//In main:
ArrayElement* list = new ArrayElement[NUM_OF_ELEMENTS];
void swap(ArrayElement list[], int index1, int index2) {
char temp[SIZE_OF_ELEMENT];
strcpy(temp, list[index2].data);
strcpy(list[index2].data, list[index1].data);
strcpy(list[index1].data, temp);
}
The error is a segmentation fault at line 45, which is the ending curly brace of the function. This was compiled using g++. I used gbd to try and debug it and everything works correctly until it hits the curly brace.
I can give more code from the program if it is needed. I don't want to post the entire thing because this is for a class.

My best guess is, the string at list[index2].data is larger than temp[] and by copying, you overwrote the stack and the return address.
Try inserting a test for the length:
#include <iostream>
...
int n = strlen(list[index2].data);
std::cerr << "len=" << n << ", SIZE_OF_ELEMENT=" << SIZE_OF_ELEMENT << std::endl;
and see, if n (list[index2].data) is larger than SIZE_OF_ELEMENT

strcpy is a hazardous function. If the length of the input string is SIZE_OF_ELEMENT or more, you will write past the end of your temp array. If you must use a fixed size array as the output array in strcpy, you should test that the strcpy will work before using the function.
Even better is to switch from using char arrays to std::string.

Is data defined like this char data[SOME_CONSTANT]? If so then are you sure that SIZE_OF_ELEMENT is large enough? You are remembering the NULL terminator too, right?
If in ArrayElement data is defined like this char *data; and is allocated with malloc at a later time then are you sure that index1 has a buffer large enough for the data in index2 and vice versa? Again, you are remembering the NULL terminator too, right?

Related

accessing array with pointer giving an extra element

Ok a very basic question, but I am stuck at it. I cannot figure out the extra mysterious value at the end of the array. I just tried to traverse the array through its base address, plain and simple. But the garbage value at the end of the array remains constant every time I execute it
g++ complier 64 bit machine.
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
void printarray(int * arr){
while(*(arr)){ cout<<*arr<<" "; arr++; }
cout<<endl;
}
int main(){
int arr[] = { 3,2,4,1,5 };
printarray(arr); // prints 3,2,4,1,5,32765
return 0;
}
EDIT 1: I understand that the while will terminate whenever it comes across a 0 in the array , or if no 0 is found will go insane . But still I would want you guys to look at the following test cases
3,2,0,4,1,5 // outputs 3,2
3,2,4,1,5,7,8,9 // outputs same array correctly
3,2,4,1,5,7,8,9,10 // outputs array+ 1 varying garbage at last
//observations, this method works for even sized arrays not containing
//0, while for odd it emits an additional garbage value.
My question is if the while only breaks at 0 , why does it break at
arrayLength+1 everytime ? Also what's with this even odd length ?
An array is not terminated in any special way. What you are trying to do is not working because while(*arr) relies on a wrong assumption: that there is a 0 element at the end of the array (a sentinel) but you declare the array a {3,2,4,1,5} so there is no end element.
I think your misconcept comes from the fact that you are not getting the point that an int* is just a memory address, whenever you increment it by ++arr you are basically adjusting it by sizeof(int). Nothing more, when you reach the end of the array then the address just points after the array, to whatever value could be there.
You get the extra element(s) because there is nothing about a pointer that tells the compiler how many elements the pointer points to. When you do
while(*(arr)){...}
The while loop will continue running untill *arr == 0. Since you array doesn't contain a 0 it will keep going past the end of the array untill it finds a 0. This is undefined behavior as you are accessing memory you do not own with that pointer.
I think you may be confusing how char arrays(c-strings) work compared to other data types. When you have
char arr[] = "something";
while(*(arr)){...}
This ends at the end of the array as c-strings get a null terminator(0) added to the end of the string automatically. This allows you to do things like the above loop as you know that null terminator will be there and if it is not then that is on the person you created the string.
An array decays into a pointer when passed to a function, and this function knows nothing about the array's length.
That while(*arr) stuff is incorrect. It will stop only when some value this pointer points to is zero. But who said a zero is placed at the end of an array?? When you increment arr, you can easily get out of bounds of your array (the function doesn't know its size!), and then *arr will give you whatever the heck is stored at the memory address arr points to at the moment.
To iterate over an array, pass the array itself and its length. Otherwise this will iterate over and over until the value of *arr will be zero.
Pointers aren't terminated in C++ by any character.
This works on other types like char* only because it's terminated by an \0(0).
An INT-Array u need to count the Elements before you can pass them into something like that, for example here with the ending 5 from your Pointer:
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
void printarray(int * arr){
int *saved=arr;
while(*saved!=5)
{
cout<<*saved++<<" ";
}
*saved=0;
cout<<endl;
}
int main(){
int arr[] = { 3, 2, 4, 1, 5 };
printarray(arr); // prints now without ending 5.
return 0;
}
Otherwise, you need to pass the counter of elements.
There is no way C++ could know how many elements your pointer points to.

strcpy works fine, even though memory is not allocated

Below c++ program works fine, even though i have not allocated any memory to chr.
I went through google, SO and came across this
Why does this intentionally incorrect use of strcpy not fail horribly?
Here the program works fine for destination which has space less than the source.
Does that apply in my case also,strcpy writes into a random location in the heap?
#include<iostream>
using namespace std;
class Mystring
{
char *chr;
int a;
public:
Mystring(){}
Mystring(char *str,int i);
void Display();
};
Mystring::Mystring(char *str, int i)
{
strcpy(chr,str);
a = i;
}
void Mystring::Display()
{
cout<<chr<<endl;
cout<<a<<endl;
}
int main()
{
Mystring a("Hello world",10);
a.Display();
return 0;
}
output:-
Hello world
10
I tried the same thing with another c++ program, with any class and class member, and i was able to see the crash.
#include<iostream>
using namespace std;
int main()
{
char *src = "Hello world";
char *dst;
strcpy(dst,src);
cout<<dst<<endl;
return 0;
}
Please help me understand the behavior in the first c++ program.Is memory allocated somehow or strcpy is writing to some random memory location.
The behavior of your program is undefined by the C++ standard.
This means that any C++ implementation (e.g. a compiler) can do whatever it wants. Printing "hello!" on stdout would be a possible outcome. Formatting the hard disk would still be acceptable, as far as the C++ standard is involved. Practically, though, some random memory on the heap will be overwritten, with unpredictable consequences.
Note that the program is even allowed to behave as expected. For now. Unless it's Friday. Or until you modify something completely unrelated. This is what happened in your case, and is one of the worst thing to happen from the point of view of a programmer.
Later on, you may add some code and see your program crash horribly, and think the problem lies in the code you just added. This can cause you to spend a long time debugging the wrong part of the code. If that ever happens, welcome to hell.
Because of this, you should never, ever, rely on undefined behavior.
strcpy() is indeed writing to a random location.
And it's a blind luck if your program runs fine and nothing crashes.
You have created on object of MyString class on a stack. In that object there's a member pointer chr, which points to some arbitrary location. Does your constructor take care to initialize that pointer or allocate a memory for the pointer to point at? -- No, it doesn't. So chr points somewhere.
strcpy() in its turn doesn't care about any pointer validity, it trusts your professionalism to provide valid input. So it does its job copying stings. Luckily, overwriting memory at the location pointed by an uninitialized chr doesn't crash you program, but that's "luckily" only.
It is known that strcpy() can cause overflow errors, because there is no check made wherever the data will fit in the new array or not.
The outcome of this overflow may sometime never been noticed, it all depends on where the data is written. However a common outcome is heap and/or program corruption.
A safe alternative of strcpy() is the usage of strcpy_s() that requires also the size of the array. You can read more about the usage of strcpy_s() on MSDN or here
Actually, strcpy() does something like this:
char *strcpy(char *dest, const char *src)
{
unsigned i;
for (i=0; src[i] != '\0'; ++i)
dest[i] = src[i];
dest[i] = '\0';
return dest;
}
So, when you pass a pointer to some character array to strcpy, it copies data from src to dest until it reaches NULL terminated character.
Character pointer does not contain any information about length of string, so when you pass dest pointer, it copies data even though you haven't assigned memory to it.
Run this example code, you will get my point:
#include <cstring>
#include <iostream>
using namespace std;
int main()
{
char str1[] = "Hello_World!";
char str2[5];
char str3[10];
strcpy(str2,str1);
cout << "string 1:" << str1 << endl;
cout << "string 2:" << str2 << endl;
cout << "string 3:" << str3 << endl;
return 0;
}
This will not show any error but you can understand by my example that this is not a good practice.

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.

Pass character array by value and return a new character array from the function?

I apologise if I'm completely misunderstanding C++ at the moment, so my question might be quite simple to solve. I'm trying to pass a character array into a function by value, create a new array of the same size and fill it with certain elements, and return that array from the function. This is the code I have so far:
char *breedMutation(char genome []){
size_t genes = sizeof(genome);
char * mutation = new char[genes];
for (size_t a = 0 ;a < genes; a++) {
mutation[a] = 'b';
}
return mutation;
}
The for loop is what updates the new array; right now, it's just dummy code, but hopefully the idea of the function is clear. When I call this function in main, however, I get an error of initializer fails to determine size of ‘mutation’. This is the code I have in main:
int main()
{
char target [] = "Das weisse leid"; //dummy message
char mutation [] = breedMutation(target);
return 0;
}
I need to learn more about pointers and character arrays, which I realise, but I'm trying to learn by example as well.
EDIT: This code, which I'm trying to modify for character arrays, is the basis for breedMutation.
int *f(size_t s){
int *ret=new int[s];
for (size_t a=0;a<s;a++)
ret[a]=a;
return ret;
}
Your error is because you can't declare mutation as a char[] and assign it the value of the char* being returned by breedMutation. If you want to do that, mutation should be declared as a char* and then deleted once you're done with it to avoid memory leaks in a real application.
Your breedMutation function, apart from dynamically allocating an array and returning it, is nothing like f. f simply creates an array of size s and fills each index in the array incrementally starting at 0. breedMutation would just fill the array with 'b' if you didn't have a logic error.
That error is that sizeof(genome); will return the size of a char*, which is generally 4 or 8 bytes on a common machine. You'll need to pass the size in as f does since arrays are demoted to pointers when passed to a function. However, with that snippet I don't see why you'd need to pass a char genome[] at all.
Also, in C++ you're better off using a container such as an std::vector or even std::array as opposed to dynamically allocated arrays (ones where you use new to create them) so that you don't have to worry about freeing them or keeping track of their size. In this case, std::string would be a good idea since it looks like you're trying to work with strings.
If you explain what exactly you're trying to do it might help us tell you how to go about your problem.
The line:
size_t genes = sizeof(genome);
will return the sizeof(char*) and not the number of elements in the genome array. You will need to pass the number of elements to the breedMutation() function:
breedMutation(target, strlen(target));
or find some other way of providing that information to the function.
Hope that helps.
EDIT: assuming it is the number of the elements in genome that you actually want.
Array are very limited.
Prefer to use std::vector (or std::string)
std::string breedMutation(std::string const& genome)
{
std::string mutation;
return mutation;
}
int main()
{
std::string target = "Das weisse leid"; //dummy message
std::string mutation = breedMutation(target);
}
Try replacing the second line of main() with:
char* mutation = breedMutation(target);
Also, don't forget to delete your mutation variable at the end.

C++ Why is this passed-by-reference array generating a runtime error?

void pushSynonyms (string synline, char matrizSinonimos [1024][1024]){
stringstream synstream(synline);
vector<int> synsAux;
int num;
while (synstream >> num) {synsAux.push_back(num);}
int index=0;
while (index<(synsAux.size()-1)){
int primerSinonimo=synsAux[index];
int segundoSinonimo=synsAux[++index];
matrizSinonimos[primerSinonimo][segundoSinonimo]='S';
matrizSinonimos [segundoSinonimo][primerSinonimo]='S';
}
}
and the call..
char matrizSinonimos[1024][1024];
pushSynonyms("1 7", matrizSinonimos)
It's important for me to pass matrizSinonimos by reference.
Edit: took away the & from &matrizSinonimos.
Edit: the runtime error is:
An unhandled win32 exception occurred in program.exe [2488]![alt text][1]
What's wrong with it
The code as you have it there - i can't find a bug. The only problem i spot is that if you provide no number at all, then this part will cause harm:
(synsAux.size()-1)
It will subtract one from 0u . That will wrap around, because size() returns an unsigned integer type. You will end up with a very big value, somewhere around 2^16 or 2^32. You should change the whole while condition to
while ((index+1) < synsAux.size())
You can try looking for a bug around the call side. Often it happens there is a buffer overflow or heap corruption somewhere before that, and the program crashes at a later point in the program as a result of that.
The argument and parameter stuff in it
Concerning the array and how it's passed, i think you do it alright. Although, you still pass the array by value. Maybe you already know it, but i will repeat it. You really pass a pointer to the first element of this array:
char matrizSinonimos[1024][1024];
A 2d array really is an array of arrays. The first lement of that array is an array, and a pointer to it is a pointer to an array. In that case, it is
char (*)[1024]
Even though in the parameter list you said that you accept an array of arrays, the compiler, as always, adjusts that and make it a pointer to the first element of such an array. So in reality, your function has the prototype, after the adjustments of the argument types by the compiler are done:
void pushSynonyms (string synline, char (*matrizSinonimos)[1024]);
Although often suggested, You cannot pass that array as a char**, because the called function needs the size of the inner dimension, to correctly address sub-dimensions at the right offsets. Working with a char** in the called function, and then writing something like matrizSinonimos[0][1], it will try to interpret the first sizeof(char**) characters of that array as a pointer, and will try to dereference a random memory location, then doing that a second time, if it didn't crash in between. Don't do that. It's also not relevant which size you had written in the outer dimension of that array. It rationalized away. Now, it's not really important to pass the array by reference. But if you want to, you have to change the whole thingn to
void pushSynonyms (string synline, char (&matrizSinonimos)[1024][1024]);
Passing by reference does not pass a pointer to the first element: All sizes of all dimensions are preserved, and the array object itself, rather than a value, is passed.
Arrays are passed as pointers - there's no need to do a pass-by-reference to them. If you declare your function to be:
void pushSynonyms(string synline, char matrizSinonimos[][1024]);
Your changes to the array will persist - arrays are never passed by value.
The exception is probably 0xC00000FD, or a stack overflow!
The problem is that you are creating a 1 MB array on the stack, which probably is too big.
try declaring it as:
void pushSynonyms (const string & synline, char *matrizSinonimos[1024] )
I believe that will do what you want to do. The way you have it, as others have said, creates a 1MB array on the stack. Also, changing synline from string to const string & eliminates pushing a full string copy onto the stack.
Also, I'd use some sort of class to encapsulate matrizSinonimos. Something like:
class ms
{
char m_martix[1024][1024];
public:
pushSynonyms( const string & synline );
}
then you don't have to pass it at all.
I'm at a loss for what's wrong with the code above, but if you can't get the array syntax to work, you can always do this:
void pushSynonyms (string synline, char *matrizSinonimos, int rowsize, int colsize )
{
// the code below is equivalent to
// char c = matrizSinonimos[a][b];
char c = matrizSinonimos( a*rowsize + b );
// you could also Assert( a < rowsize && b < colsize );
}
pushSynonyms( "1 7", matrizSinonimos, 1024, 1024 );
You could also replace rowsize and colsize with a #define SYNONYM_ARRAY_DIMENSION 1024 if it's known at compile time, which will make the multiplication step faster.
(edit 1) I forgot to answer your actual question. Well: after you've corrected the code to pass the array in the correct way (no incorrect indirection anymore), it seems most probable to me that you did not check you inputs correctly. You read from a stream, save it into a vector, but you never checked whether all the numbers you get there are actually in the correct range. (end edit 1)
First:
Using raw arrays may not be what you actually want. There are std::vector, or boost::array. The latter one is compile-time fixed-size array like a raw-array, but provides the C++ collection type-defs and methods, which is practical for generic (read: templatized) code.
And, using those classes there may be less confusion about type-safety, pass by reference, by value, or passing a pointer.
Second:
Arrays are passed as pointers, the pointer itself is passed by value.
Third:
You should allocate such big objects on the heap. The overhead of the heap-allocation is in such a case insignificant, and it will reduce the chance of running out of stack-space.
Fourth:
void someFunction(int array[10][10]);
really is:
(edit 2) Thanks to the comments:
void someFunction(int** array);
void someFunction(int (*array)[10]);
Hopefully I didn't screw up elsewhere....
(end edit 2)
The type-information to be a 10x10 array is lost. To get what you've probably meant, you need to write:
void someFunction(int (&array)[10][10]);
This way the compiler can check that on the caller side the array is actually a 10x10 array. You can then call the function like this:
int main() {
int array[10][10] = { 0 };
someFunction(array);
return 0;
}