This question already has answers here:
No out of bounds error
(7 answers)
Closed 1 year ago.
I'm working on dynamic arrays for my c++ course, but I'm confused about the behavior of my dynamic arrays. For example, if I run this code:
int* myDynamicArr = new int[3];
for (int i = 0; i < 10; i++)
{
myDynamicArr[i] = i + 1;
cout << myDynamicArr[i] << endl;
}
I would expect it to not work since I only declared it as size 3. But when I run it, it prints out 0-9. Same thing if I do this:
char* myCharArr = new char[2];
strcpy(myCharArr, "ThisIsALongString");
cout << myCharArr;
It prints the full string even though it seems like it should fail. Can anyone explain what I'm doing wrong here? Thanks!
C++ does not perform bounds checking on arrays. So when you read or write past the bounds of an array you trigger undefined behavior.
With undefined behavior, your program may crash, it may output strange results, or it may (as in your case) appear to work properly.
Just because it could crash doesn't mean it will.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
first post here so be gentle. I'm trying execute a recursive binary search. I have tried different variations of code to try to make the function work but i still doesnt.
Here's my code:
bool contained(int x, const int* pBegin, const int* pEnd){
if(x==*pBegin) { //
return pBegin;
}
int size = pEnd - pBegin; //size of the array
int mid= size/2; //the middle of the array
int const* pMid = pBegin + mid; //The address of the element in the middle of the array
if(x>*pMid) //Condition that looks if x is to the left of the array
return contained(x,pMid,pEnd);
else if(x<*pMid) //Condition that looks if x is to the right of the array
return contained(x,pBegin,pMid-1);
}
int main()
{
cout << "Binary search, test: " << endl;
int arr[] = {1,2,3,4,5,7,8,9};
int size = 9;
for(int i=0; i<size; i+=1)
arr[i] = i;
bool find = containedInSortedarray(6, &arr[0], &arr[size]);
cout << "Found " << find << endl;
}
For example here, when i execute my bool-contained function with a premade array and let it search for the value 6, it should eventually come to the conclusion that the element does not exist, yet my output says it does. Have i missed something in my code?
Thanks in advance!
There are a couple of issues with your code:
You never return false.
You return pBegin which is not a bool, (sadly in your case) it is implicitly convertible to one, but not in the way you want it too. Turn on your compiler warnings all the way up - -Wextra -Wall -pedantic -Werror should be the bare minimum, especially if you are a beginner.
Be precise about the interval your function searches in. func(x,a,b) - does it include b? Based on contained(x,pBegin,pMid-1); it seems it does, but in the case of containedInSortedarray(6, &arr[0], &arr[size]); hopefully not.
Dereferencing &arr[size] is UB.
What is the purpose of the for loop in main?
Having the size detached from the array is a disaster waiting to happen. At least use sizeof(arr)/sizeof(arr[0]). Better yet, use std::array or a std::vector.
I would suggest searching [a,b) because it can be easily be divided into [a,mid), [mid,end). That way your mid computation is already correct. You can then call it like containedInSortedarray(x,arr,arr+arr_size)
The base condition should catch the arrays of size 0 and 1 - both can be trivially tested for presence of x.
I am trying to write a lexer, when I try to copy isdigit buffer value in an array of char, I get this core dumped error although I have done the same thing with identifier without getting error.
#include<fstream>
#include<iostream>
#include<cctype>
#include <cstring>
#include<typeinfo>
using namespace std;
int isKeyword(char buffer[]){
char keywords[22][10] = {"break","case","char","const","continue","default", "switch",
"do","double","else","float","for","if","int","long","return","short",
"sizeof","struct","void","while","main"};
int i, flag = 0;
for(i = 0; i < 22; ++i){
if(strcmp(keywords[i], buffer) == 0)
{
flag = 1;
break;
}
}
return flag;
}
int isSymbol_Punct(char word)
{
int flag = 0;
char symbols_punct[] = {'<','>','!','+','-','*','/','%','=',';','(',')','{', '}','.'};
for(int x= 0; x< 15; ++x)
{
if(word==symbols_punct[x])
{
flag = 1;
break;
}
}
return flag;
}
int main()
{
char buffer[15],buffer1[15];
char identifier[30][10];
char number[30][10];
memset(&identifier[0], '\0', sizeof(identifier));
memset(&number[0], '\0', sizeof(number));
char word;
ifstream fin("program.txt");
if(!fin.is_open())
{
cout<<"Error while opening the file"<<endl;
}
int i,k,j,l=0;
while (!fin.eof())
{
word = fin.get();
if(isSymbol_Punct(word)==1)
{
cout<<"<"<<word<<", Symbol/Punctuation>"<<endl;
}
if(isalpha(word))
{
buffer[j++] = word;
// cout<<"buffer: "<<buffer<<endl;
}
else if((word == ' ' || word == '\n' || isSymbol_Punct(word)==1) && (j != 0))
{
buffer[j] = '\0';
j = 0;
if(isKeyword(buffer) == 1)
cout<<"<"<<buffer<<", keyword>"<<endl;
else
{
cout<<"<"<<buffer<<", identifier>"<<endl;
strcpy(identifier[i],buffer);
i++;
}
}
else if(isdigit(word))
{
buffer1[l++] = word;
cout<<"buffer: "<<buffer1<<endl;
}
else if((word == ' ' || word == '\n' || isSymbol_Punct(word)==1) && (l != 0))
{
buffer1[l] = '\0';
l = 0;
cout<<"<"<<buffer1<<", number>"<<endl;
// cout << "Type is: "<<typeid(buffer1).name() << endl;
strcpy(number[k],buffer1);
k++;
}
}
cout<<"Identifier Table"<<endl;
int z=0;
while(strcmp(identifier[z],"\0")!=0)
{
cout <<z<<"\t\t"<< identifier[z]<<endl;
z++;
}
// cout<<"Number Table"<<endl;
// int y=0;
// while(strcmp(number[y],"\0")!=0)
// {
// cout <<y<<"\t\t"<< number[y]<<endl;
// y++;
// }
}
I am getting this error when I copy buffer1 in number[k] using strcpy. I do not understand why it is not being copied. When i printed the type of buffer1 to see if strcpy is not generating error, I got A_15, I searched for it, but did not find any relevant information.
The reason is here (line 56):
int i,k,j,l=0;
You might think that this initializes i, j, k, and l to 0, but in fact it only initializes l to 0. i, j, and k are declared here, but not initialized to anything. As a result, they contain random garbage, so if you use them as array indices you are likely to end up overshooting the bounds of the array in question.
At that point, anything could happen—in other words, this is undefined behavior. One likely outcome, which is probably happening to you, is that your program tries to access memory that hasn't been assigned to it by the operating system, at which point it crashes (a segmentation fault).
To give a concrete demonstration of what I mean, consider the following program:
#include <iostream>
void print_var(std::string name, int v)
{
std::cout << name << ": " << v << "\n";
}
int main(void)
{
int i, j, k, l = 0;
print_var("i", i);
print_var("j", j);
print_var("k", k);
print_var("l", l);
return 0;
}
When I ran this, I got the following:
i: 32765
j: -113535829
k: 21934
l: 0
As you can see, i, j, and k all came out such that using them as indices into any of the arrays you declared would exceed their bounds. Unless you are very lucky, this will happen to you, too.
You can fix this by initializing each variable separately:
int i = 0;
int j = 0;
int k = 0;
int l = 0;
Initializing each on its own line makes the initializations easier to see, helping to prevent mistakes.
A few side notes:
I was able to spot this issue immediately because I have my development environment configured to flag lines that provoke compiler warnings. Using a variable before it's being initialized should provoke such a warning if you're using a reasonable compiler, so you can fix problems like this as you run into them. Your development environment may support the same feature (and if it doesn't, you might consider switching to something that does). If nothing else, you can turn on warnings during compilation (by passing -Wall -Wextra to your compiler or the like—check its documentation for the specifics).
Since you declared your indices as int, they are signed integers, which means they can hold negative values (as j did in my demonstration). If you try to index into an array using a negative index, you will end up dereferencing a pointer to a location "behind" the start of the array in memory, so you will be in trouble even with an index of -1 (remember that a C-style array is basically just a pointer to the start of the array). Also, int probably has only 32 bits in your environment, so if you're writing 64-bit code then it's possible to define arrays too large for an int to fully cover, even if you were to index into the array from the middle. For these sorts of reasons, it's generally a good idea to type raw array indices as std::size_t, which is always capable of representing the size of the largest possible array in your target environment, and also is unsigned.
You describe this as C++ code, but I don't see much C++ here aside from the I/O streams. C++ has a lot of amenities that can help you guard against bugs compared to C-style code (which has to be written with great care). For example, you could replace your C-style arrays here with instances of std::array, which has a member function at() that does subscripting with bounds checking; that would have thrown a helpful exception in this case instead of having your program segfault. Also, it doesn't seem like you have a particular need for fixed-size arrays in this case, so you may better off using std::vector; this will automatically grow to accommodate new elements, helping you avoid writing outside the vector's bounds. Both support range-based for loops, which save you from needing to deal with indices by hand at all. You might enjoy Bjarne's A Tour of C++, which gives a nice overview of idiomatic C++ and will make all the wooly reference material easier to parse. (And if you want to pick up some nice C habits, both K&R and Kernighan and Pike's The Practice of Programming can save you much pain and tears).
Some general hints that might help you to avoid your cause of crash totally by design:
As this is C++, you should really refer to established C++ data types and schemes here as far as possible. I know, that distinct stuff in terms of parser/lexer writing can become quite low-level but at least for the things you want to achieve here, you should really appreciate that. Avoid plain arrays as far as possible. Use std::vector of uint8_t and/or std::string for instance.
Similar to point 1 and a consequence: Always use checked bounds iterations! You don't need to try to be better than the optimizer of your compiler, at least not here! In general, one should always avoid to duplicate container size information. With the stated C++ containers, this information is always provided on data source side already. If not possible for very rare cases (?), use constants for that, directly declared at/within data source definition/initialization.
Give your variables meaningful names, declare them as local to their used places as possible.
isXXX-methods - at least your ones, should return boolean values. You never return something else than 0 or 1.
A personal recommendation that is a bit controversional to be a general rule: Use early returns and abort criteria! Even after the check for file reading issues, you proceed further.
Try to keep your functions smart and non-boilerplate! Use sub-routines for distinct sub-tasks!
Try to avoid using namespace that globally! Even without exotic building schemes like UnityBuilds, this can become error-prone as hell for huger projects at latest.
the arrays keywords and symbols_punct should be at least static const ones. The optimizer will easily be able to recognize that but it's rather a help for you for fast code understanding at least. Try to use classes here to compound the things that belong together in a readable, adaptive, easy modifiable and reusable way. Always keep in mind, that you might want to understand your own code some months later still, maybe even other developers.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
A picture of memory output debugging stuff
the W, S, G are W( base class ) S( derived from base W ), G( derived from base W ). S has two extra floats that W doesn't, G has a bool W doesn't.
the numbers following the letters is just sizeof( W/S/G ).
the ants are made like so
W* _ants = new S[ 6 ];
and the function giving the problem is called like so
for( int i = 0; i < 6; i++ )
{
std::cout << "Ant " << i << ": " << &_ants[ i ] << std::endl;
_ants[ i ].update();
}
update is a non-virtual method from W, though it does call a virtual method within it. I have tried removing the virtual method but it still crashes.
I'm pretty sure the problem is that the array is trying to allocate for W but since it is 8 bytes smaller than S _ants goes off track at 1 iteration, is there anyway I can get _ants to allocate the correct amount per iteration without trying to change it to S* or at least keep it on track somehow?
This is one of the best reasons you should not use C-style arrays in C++ unless you have no choice. The language can't easily distinguish between a pointer to a single instance and a pointer to an array, so it cannot detect when you use the latter in an instance where only the former is legal.
W* _ants = new S[ 6 ];
This is setting you up to fail. The array of 6 S objects lays them out in memory sizeof(S) bytes, plus padding, apart.
So what's going on here? The type on the right is S*. While here it points to an array, the conversion to W* is allowed because the same type could point to a single object. While converting a pointer to a single instance of a derived type to a pointer to its base is perfectly legal, it is impossible to do the same thing for a pointer to an array. The memory layout is just not the same.
_ants[ i ].update();
And then here you fail. This adds i * sizeof(W) bytes to _ants, which does not match the layout.
See here for more information.
Your reasoning is correct for why it's misaligned. You shouldn't use arrays polymorphically. Instead of having an array of Ws, use could use an array of W*s. This is one way to work around this problem:
W** _ants = new W*[6];
for( int i = 0; i < 6; i++ )
ants[i] = new S(...);
}
//...
for( int i = 0; i < 6; i++ )
{
_ants[ i ]->update();
}
Your problem is that your memory is not going to line up. When you do
W* _ants = new S[ 6 ];
You now allocated enough space for 6 S but you are using a pointer of type W to traverse it. Since W is smaller than S after the first iterator you will point to memory that is the end of the first S and part of the second S
If you want to store 6 S* in a W* container then I suggest you use a std::vector and do something like:
std::vector<W*> data;
for (int i = 0; i < some_number; i++)
{
data.push_back(new S());
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
I am making a simple Lottery program - and am struggling with implementation. I have a class called 'Ticket Line' this class simply holds 6 numbers that the player is playing a lottery for.
What I want to do, is generate 6 randomly (got function for this already) and then store that in another class as values. To do this, I am using the following code:
class Draw
{
private:
int drawID;
TicketLine* DrawnNumbers;
bool drawn;
}
When a Draw is completed I want to generate the Random Numbers ( from the TicketLine class) and then for the Draw to be able to store those numbers into its Draw File.
How would I be able to access the functionality of the DrawnNumbers class - and store the results from the getTicketNumbers.getTicketLine()function.
int* getTicketNumbers(void) { return DrawnNumbers->getTicketLine();};
The program crashes the following code:
//int *ptr[6] = getTicketNumbers();
int *ptr[6] = getTicketNumbers();
for (int x = 0; x < 6; x++){
cout << ptr[x];
}
TicketLine class:
private:
int select[6]; //Array of Ticket Numbers.
int* getTicketLine(void) { return select; };
I am willing to offer a couple of virtual beers to the solution. I am as yet to find a good online pub - if you know of one then please do let me know :-)
Thanks,
Without knowing any more, this line:
int *ptr[6] = getTicketNumbers();
is very suspect.
Why? Well, we haven't seen the implementation of getTicketNumbers so we don't know if it's actually allocating memory for 6 and returning such an array.
Also, you are printing the values of pointers here:
for (int x = 0; x < 6; x++){
cout << ptr[x];
}
Where, if you intended to actually print the int values, you'd say something like this:
for (int x = 0; x < 6; x++){
cout << *(ptr[x]);
}
My guess is that you are either:
Going out of bounds of an array that was (not) allocated, or,
Modifying actual pointer values somewhere instead of the integers they point to (as indicated by your lack of dereferencing ptr[x] in your print statement)
Edit
With more information, it seems you probably meant to say this:
int *ptr = getTicketNumbers();
instead of this:
int *ptr[6] = getTicketNumbers();
You should probably be doing some sanity checks as well to make sure that select is actually filled before calling that function (maybe giving it a default value of {0,0,0,0,0,0} in the constructor)
DrawnNumbers doesn't appear to be pointing to anything yet. It's a pointer, but to what?
Also, be careful about returning arrays that way. If the object or stack frame that the array resides in goes away, you'll be left pointing to bad things.