This question already has answers here:
Accessing an array out of bounds gives no error, why?
(18 answers)
Closed 7 years ago.
While debugging I found an error with an int array of 0. In a test document I messed around with array with more cell input than their length.
int array[0];
for(int i = 0; i < 10; i++)
array[i] = i;
for(int i = 0; i < 10; i++)
cout << array[i];
After I compiled and ran the program I got
0123456789
Then I received the message "test.exe has stopped working". I expected both of these, but what I am confused about is why the compiler lets me create an array of 0, and why the program doesn't crash until the very end of the program. I expected the program to crash once I exceeded the array length.
Can someone explain?
The compiler should have at least warned you about a zero size array - if it didn't .. consider changing compiler.
Remember that an array is just a bit of memory just like any other. In your example the array is probably stored on the stack and so writing off the end of it may not cause much of a problem until your function exits. At that point you may find you have written some text over the return address and you get an exception. Writing off the end of arrays are a common cause of bugs in C/C++ - just be thankful you got an error with this one and it didn't just overwrite some other unrelated data.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I am trying to solve a problem for code wars, but my code gives an error. I've tested the code on code blocks and it works, but when I test it on their website it gives me some strange error. I looked it on the internet and found out that it might be a segmentation fault because of a deref of a null pointer, but I dont know how to fix it. This is my code and the error. Can you tell me plase what is the problem and why it works on code block, but on the compiler on the website it doesn't.(P.S. Please excuse my english, Im from Romania).
#include <iostream>
#include <vector>
#include <bits/stdc++.h>
using namespace std;
long queueTime(std::vector<int> costumers, int n) {
vector<int> q;
int j, x;
long t;
for (j = 0; j < n; j++)
q.push_back(costumers[j]);
int u = costumers.size();
while (j <= u) {
x = *min_element(q.begin(), q.end());
t = t + x;
for (int i = 0; i < n; i++) {
q[i] = q[i] - x;
if (q[i] == 0) {
q[i] = costumers[j];
j++;
}
}
}
t += *max_element(q.begin(), q.end());
return t;
}
Error message:
UndefinedBehaviorSanitizer:DEADLYSIGNAL
==1==ERROR: UndefinedBehaviorSanitizer: SEGV on unknown address 0x000000000000 (pc 0x00000042547b bp 0x000000000000 sp 0x7ffec8fa0510 T1)
==1==The signal is caused by a READ memory access.
==1==Hint: address points to the zero page.
==1==WARNING: invalid path to external symbolizer!
==1==WARNING: Failed to use and restart external symbolizer!
#0 0x42547a (/workspace/test+0x42547a)
#1 0x427ffc (/workspace/test+0x427ffc)
#2 0x42686e (/workspace/test+0x42686e)
#3 0x426435 (/workspace/test+0x426435)
#4 0x42609b (/workspace/test+0x42609b)
#5 0x42aad5 (/workspace/test+0x42aad5)
#6 0x42581d (/workspace/test+0x42581d)
#7 0x7fc90f605b96 (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
#8 0x404489 (/workspace/test+0x404489)
UndefinedBehaviorSanitizer can not provide additional info.
==1==ABORTING
SEGV would indicate that there is a segmentation fault happening somewhere so you are on the right track with your debugging. Looking at the code you have provided there are few tips that might help you narrow down where things are going wrong.
The first thing that sticks out is that seem to be taking a local copy of costumers on this line:
for (j = 0; j < n; j++) q.push_back(costumers[j]);
Here you make the assumption that n is less or equal to costumers.size() and if n is larger than this then this will try to read from beyond the end of the vector. An alternative here is to use the = operator instead:
vector<int> q = costumers;
If you actually only wanted the first n elements of costumers copied to q then you could use:
if(n < q.size()){
q.resize(n);
}
to shrink it to size afterwards.
Another general style point is that it is good practice to something called "Resource allocation is initialization" (RAII): at the top of your queueTime function you have a bunch of variables declared but not initialized to values:
int j, x;
long t;
The problem here is that these will often be initialized to junk values and if you forget to initialize them later then you may be reading these junk values without knowing. Try instead to declare the variable at the point in the code you assign a value to it, eg fo j:
for(int j = 0; ... )
and x
int x = *min_element(q.begin(), q.end());
or in the case where you need t everywhere in the function scope, at least assign an initial value when you declare it
long t = 0;
Finally when using algorithms that return iterators it is generally good practice to check that they are valid before dereferencing them ie. writing:
auto itr_min_elem = min_element(q.begin(), q.end());
if(itr_min_elem == q.end()){
continue;
}
int x = *itr_min_elem;
so that if q is empty and min_element returns an end iterator then you don't try to dereference it.
Sorry for the wall of text but I hope these offer some help for debugging your function.
As a general note to your question about why it was working on code blocks but not on the website could come down to a number of reasons, likely related to how the code is being compiled. Some compilers will initialize memory to 0s in debug builds and this can have the effect of uninitialized variables behaving nicely in debug but in an undefined way in release. Also depending on the environment the code is executed in there may be differences in the memory layout so reading past the end of an array in one environment may just give junk while in another you may be indexing into protected memory or outside of your programs allocated memory. This would cause the platform running your code to be very unhappy and force it to abort.
This question already has an answer here:
will Index Out Of Array Bounds throw exception or error before core in C++?
(1 answer)
Closed 5 years ago.
I have this code:
#include <cstdio>
int foo[100];
int main()
{
for(int i=0;i<10000;i++)
foo[i]=10000;
}
Debugging with GDB gives a surprising result:
[New Thread 23684.0x59b4]
[New Thread 23684.0x5c0c]
[New Thread 23684.0x541c]
Program received signal SIGSEGV, Segmentation fault.
0x0000000000401564 in main () at C:\Users\DARREN\Documents\Visual Studio
2017\Projects\Untitled1.cpp:9
warning: Source file is more recent than executable.
9 }
(gdb) print i
$1 = 4080
(gdb)
Now, I know the statement foo[i]=10000 caused the error, but I declared foo to be only of size 100. Why would the value of i be so big before the error occurs?
Any explanation is appreciated.
After you made an update to your question you posted this:
int foo[100];
int main()
{
for(int i=0;i<10000;i++)
foo[i]=10000;
}
And you are asking about segmentation fault.
Here you have an array with a size of 100 and you have a loop that ranges [0,9999] and within the for loop you are indexing the array with the for loops incremental variable i. When you step through the for loop for each iteration of i and you get to:
foo[i] = 10000;
when i <= 99 everything is okay.
What do you suppose happens when i >= 100?
When you use raw arrays there is no bounds checking; and this is something that you and the user will have to be responsible for. If you want automatic bounds checking done for you to prevent this out of bounds memory segmentation fault you should use any of the standard containers such as std::vector<T>, std::list<T>, std::set<T> etc. depending on your needs. If you need to use array index notation then std::vector<T> is the way to go. Or any other vector from any other library such as boost.
EDIT
For you to fix this problem you would have to either increase the size of the array from 100 to 10,000 or you would have to decrease your loop's condition from i<10000 to i<100 to accommodate for proper array indexing. Do not forget that C++ arrays have their starting index at 0 so you would have a basic array and loop as such:
int var[10]; // Uninitialized
for ( int i = 0; i < 10; ++i ) {
var[i] = 0; // Initialize all array indexes to 0
}
Notice that the condition in the for loop is i < 10 which is less than the actual size of the array when it is declared and not i <= 10 less than or equal to for this would also generate a segmentation fault or out of bounds error.
The following code is causing a EXC_BAD_ACCESS address 0x0 error - even when i is correct somehow. It's used to execute the arrays pointed to the functions. If I change the sizeof(draw); with the number i have, it just works as expected.
for(int i = 0; i < sizeof(draw); i++)
draw[i](i);
sizeof(draw) returns the size of "draw" in number of bytes, not number of items. You are probably looking for (sizeof(draw)/sizeof(draw[0]))
This question already has answers here:
Why does "memset(arr, -1, sizeof(arr)/sizeof(int))" not clear an integer array to -1?
(6 answers)
Closed 8 years ago.
Here is the code:
#include <iostream>
#include <cstring>
int main()
{
int win[11];
std::memset(win, 1, sizeof(win));
for (int i = 0; i < 11; ++i)
std::cout << win[i] << ' ';
std::cout << std::endl;
return 0;
}
I think there is no logic flaw here? But instead of getting a string of 1 printed, I got 16843009.
If I change the memset to std::memset(win, 0, sizeof(win)). Then everything is as expected. The content of win is all zeros.
Am I missing something here?
I'm using g++ 4.7.3 on Ubuntu 13.04.
Sorry for this duplicated question.
Here is the answer. Thanks
Why does "memset(arr, -1, sizeof(arr)/sizeof(int))" not clear an integer array to -1?
ints are usually four bytes long. But memset sets the value of individual bytes, so you're setting each value to 0x01010101, which just so happens to equal 16843009.
The memset function writes over memory without understanding its structure in any way. If you write a bunch of random 1's all over an accounting report, will that make the report show that the company has spent $1? I don't think so. Maybe it will show 111111 dollars. Maybe not. Who knows.
To modify an object's value intelligently, you have to understand its structure. The memset function does not understand the structure of win and just scribbles 1 all over its bytes. What that means, memset does not know or care.
This question already has answers here:
Why doesn't this program segfault?
(1 answer)
Why doesn't this code cause a segfault?
(3 answers)
Closed 9 years ago.
I wrote the following after noticing something weird happening in another project. This code does not produce a segfault even though arrays are being called out of bounds multiple times. Can someone explain to me why there is no segfault from running the code below?
#include <stdlib.h>
#include <stdio.h>
int main()
{
int *a = (int *)malloc(4 * sizeof(int));
int *b = (int *)malloc(3 * sizeof(int));
int i = 0;
for(i =0; i <3 ; i++)
{
b[i] = 3+i;
}
for(i = 0; i < 4; i++)
{
a[i] = i;
}
for(i = 0; i < 100 ; i++){
a[i] = -1;
}
for(i = 0 ; i < 100 ; i++){
printf("%d \n", b[i]);
}
}
A segfault only happens if you try to access memory locations that are not mapped into your process.
The mallocs are taken from bigger chunks of preallocated memory that makes the heap. E.g. the system may make (or increase) the heap in 4K blocks, so reaching beyond the the bounds of your arrays will still be inside that block of heap-memory that is already allocated to your process (and from which it would assign memory for subsequent mallocs).
In a different situation (where more memory was allocated previously, so your mallocs are near the end of a heap block), this may segfault, but it is basically impossible to predict this (especially taking into account different platforms or compilers).
Undefined behaviour is undefined. Anything can happen, including the appearance of "correct" behaviour.
A segmentation fault occurs when a process tries to access memory which OS accounts as not belonging to the process. As memory accounting inside an OS is done by pages (usually 1 page = 4 KB), a process can access any memory within the allocated page without OS noticing it.
Should be using new and not malloc
What is the platform?
When you try undefined behaviour - gues what it is undefined.