I'm new to C and I've found a peculiar output from gcc that I'm having a hard time getting to the bottom of. The error upon running the application is:
*** stack smashing detected ***: /home/joshua/Research/cml/test terminated
Program received signal SIGABRT, Aborted.
0x00007ffff7a43428 in __GI_raise (sig=sig#entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
54 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
I've done some research on this, and it appears that this is many times caused by tying to put too large a value into an array, for example; I'm not doing anything like that.
Here is my sample code for reference:
1 #include <stdio.h>
2 #include <string.h>
3
4 struct student
5 {
6 int id;
7 char name[10];
8 float percentage;
9 };
10
11 int main()
12 {
13 int i;
14 struct student record[2];
15
16 // 1st student's record
17 record[0].id=1;
18 strcpy(record[0].name, "Raju");
19 record[0].percentage = 86.5;
20
21 // 2nd student's record
22 record[1].id=2;
23 strcpy(record[1].name, "Surendren");
24 record[1].percentage = 90.5;
25
26 // 3rd student's record
27 record[2].id=3;
28 strcpy(record[2].name, "Thiyagu");
29 record[2].percentage = 81.5;
30
31 for(i=0; i<3; i++)
32 {
33 printf(" Records of STUDENT : %d \n", i+1);
34 printf(" Id is: %d \n", record[i].id);
35 printf(" Name is: %s \n", record[i].name);
36 printf(" Percentage is: %f\n\n",record[i].percentage);
37 }
38 return 0;
39 }
The 2 in
struct student record[2];
is not the top index, it is the number of elements. And as you seem to know indexes start at zero which means the valid indexes are 0 and 1 for the above array. Going out of bounds leads to undefined behavior.
struct student record[2];
You've got an array of size 2 and you're trying to store 3 elements in it. Array indices go from 0 to n-1. record[2] is an invalid index.
To keep a check on the integrity of the functions, next to the return statement Gcc adds protection variables (called canaries) which have known values.In your case when the uninitialized access is done on record[2] you have violated the stacks integrity and the canary values are overwritten which trigger the crash.
Related
I have those functions and I would like to know if anyone can help me. I have to investigate why they cause a "segfault", and why it happens faster or slower depending on its conditions.
I supposed that in Rec1, it's caused by an infinite loop that collapses the memory of the memory stack. In rec2 I suppose it's caused faster because of the same condition that in Rec1 but adding that it is allocating memory everytime for the pointer too.
In Rec3 () that crashes instantly because it's allocating the same memory spot in the second iteration and causes a problem because the program is trying to access the same allocated memory.
In Rec4 () I think it's caused because it creates an array with infinite positions, ask is the limiting of the array max space.
Can you give me some advices on those suppositions?
#include <stdio.h>
#include <stdlib.h>
#define MOD 10000
int k = 0;
char global[100];
void
panic (char *m)
{
fprintf (stderr, "%s\n", m);
exit (0);
}
void
rec1 ()
{
k++;
if (k % MOD == 0)
fprintf (stderr, "%d ", k / MOD);
rec1 ();
}
void
rec2 ()
{
int *tmp;
tmp = malloc (100 * sizeof (int));
if (tmp == NULL)
exit (0);
k++;
if (k % MOD == 0)
fprintf (stderr, "%d ", k / MOD);
rec2 ();
}
void
rec3 ()
{
int tmp[100];
k++;
if (k % MOD == 0)
fprintf (stderr, "%d ", k / MOD);
rec3 ();
}
void
rec4 ()
{
global[k] = k;
if (k % 200 == 0)
fprintf (stderr, "%d ", k);
k++;
rec4 ();
}
int
main (int argc, char *argv[])
{
int mode = 1;
if (argc > 1)
mode = atoi (argv[1]);
printf ("Testing rec%d...\n", mode);
switch (mode)
{
case 1:
rec1 ();
break;
case 2:
rec2 ();
break;
case 3:
rec3 ();
break;
case 4:
rec4 ();
break;
default:
panic ("Wrong mode");
}
return 0;
}
This is the output when I run the compiled C program in terminal.
Testing rec1...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
Program received signal SIGSEGV, Segmentation fault.
0x0000555555554904 in rec1 () at stack.c:24
24 rec1 ();
Testing rec2...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7a7b96a in __GI___libc_free (mem=0x555555757670) at malloc.c:3086
3086 malloc.c: No existe el archivo o el directorio.
Testing rec3...
1
Program received signal SIGSEGV, Segmentation fault.
0x0000555555554a43 in rec3 () at stack.c:53
53 rec3 ();
Testing rec4...
0 200 400 600 800 1000 1200 1400 1600 1800 2000 2200 2400 2600 2800 3000 3200 3400 3600 3800 4000 ViolaciĆ³n de segmento (`core' generado)
Program received signal SIGSEGV, Segmentation fault.
0x0000555555554a1f in rec4 ()
The Code that you have is very likely to trigger an error in my experience. Without any compiler or program feedback, it's a little difficult to discern exactly what went wrong, but I believe you may be looking (Generally) for information regarding stacks, heaps, and recursion.
Firstly, please note that
void rec1 () {
k++;
if (k % MOD == 0)
fprintf (stderr, "%d ", k / MOD);
rec1 ();
}
is NOT "Iteration". Iteration refers to the repetition of a sequential portion of code (usually a for or while loop). What you have here is recursion. Recursion creates a new instance of the method to operate from, along with a stack pointer to navigate to the last execution point (As well as store any immediately relevant variables). This occurs every time you call the rec1 () function from your rec1 () function Eventually, you'll run out of space on the stack to store those pointers. The number of pointers you can store on a stack is usually quite large on modern computers, but considering that you have no return statement, you will run into the maximum capacity eventually.
EDIT
This post has been edited to reflect the new material presented by the question.
Okay...From the material you presented, it looks like you're essentially being asked about WHERE each rec stores and processes information...
In the case of Rec1, it does indeed appear to be a simple case of stack overflow. The pointer to the last execution point of the previous Rec1 is stored on the stack, ultimately resulting in the program's crash after about 520,000 instances. Given that each pointer is 4 bytes, that's around 2 MB of just recursive pointer information alone stored on your stack before it collapses and triggers a Seg Fault due to stack overflow.
The second case is a little trickier. Note that your program indicates that it makes it to roughly 260,000 recursions before it triggers a Seg Fault. This is exactly half of Rec1. HOWEVER, this is not necessarily a stack overflow per se. Rec2 allocates 400 bytes of data on the heap per recursion. The pointer to the heap is stored on the stack, meaning that 8 bytes are stored on the stack per recursion (which may be related to why its exactly half, but could also be explained by the ratio of your stack / heap size). Now, the error for Rec2 states that malloc could not find the file or directory, which seems to me as though malloc could not complete correctly. This may actually indicate that the max heap size has been hit.
Rec3 is pretty straightforward. The entire integer array tmp is stored on the stack for each recursion. that's 4 bytes per integer times 100 ints, which is 400 bytes on the stack PER recursion. This is no surprise that it crashes between 10,000 to 20,000 recursions. There just wasn't enough space to store the data on the stack. NOTE: In relation to something you mentioned in your question, this tmp array does not attempt to allocate the same region of memory. Due to the fact that this is recursively built, it creates a new space on the stack for that function instance.
Rec4 is a simple case of buffer overflow. After overwriting the first 100 bytes of memory allocated in global[100], it was only a matter of time before k++ would cause global[k] to point to an address space restricted to the process. This triggered the seg fault after about 4000 recursions (k was not mod 10,000 in rec4).
I hope this clarification helps.
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 4 years ago.
Improve this question
My try
int *nb=(int *)malloc(ntc*sizeof(int));// no of bus
int barr[ntc][ntc];// bus route array
int *nc=(int *)malloc(ntc*sizeof(int));// no of city
int carr[ntc][ntc];// city array
scanf("%d",&ntc); // input -> test case
for(i=0;i<ntc;i++)
{
scanf("%d",&(nb[i])); // input -> no of bus
p=2*nb[i];
for(k = 0; k < p; k++)
{
scanf("%d", &(barr[i][k])); // input -> bus route array
}
scanf("%d", &nc[i]); // input -> no of city for which bus passing by count is to be determined
q=nc[i];
for(j = 0; j < q; j++)
{
scanf("%d", &(carr[i][j])); // input -> city array
}
}
I am accepting input for various test cases. For test case#1 I am taking input of nb,barr,nc,carr arrays. This continues for ntc no of test cases. Below i have written the input statement of the problem
The first line contains the number of test cases (T), after which T
cases follow each separated from the next with a blank line. For each
test case, The first line contains the number of GBuses.(N) Second
line contains the cities covered by them in the form a1 b1 a2 b2 a3
b3...an bn where GBus1 covers cities numbered from a1 to b1, GBus2
covers cities numbered from a2 to b2, GBus3 covers cities numbered
from a3 to b3, upto N GBuses. Next line contains the number of cities
for which GBus count needs to be determined (P). The below P lines
contain different city numbers.
Suppose now input is
2
4
15 25 30 35 45 50 10 20
2
15
25
10
10 15 5 12 40 55 1 10 25 35 45 50 20 28 27 35 15 40 4 5
3
5
10
27
Now when i am printing the values just for a sanity check what i am getting is very strange.
printf("no of test case %d\n",ntc);
for(i=0;i<ntc;i++)
{
printf("Case #%d\n",i+1);
printf("no of bus %d\n",nb[i]);
p=2*nb[i];
printf("bus route array");
for(j=0;j<p;j++)
{
printf(" %d ",barr[i][j]);
}
printf("\nno of city for which bus passing by count is to be determined %d \n",nc[i]);
q=nc[i];
printf("city array");
for(k=0;k<q;k++)
{
printf(" %d ",carr[i][k]);
}
printf("\n");
}
no of test case 2
Case #1
no of bus 4
bus route array 10 15 5 12 40 55 1 10
no of city for which bus passing by count is to be determined 2
city array 5 10
Case #2
no of bus 10
bus route array 10 15 5 12 40 55 1 10 25 35 45 50 20 28 27 35 15 40 4 5
no of city for which bus passing by count is to be determined 3
city array 5 10 27
The output for Case #1 bus route should be 15 25 30 35 45 50 10 20 and not 10 15 5 12 40 55 1 10 and for city route it should be 15 25 not 5 10
int *nb=(int *)malloc(ntc*sizeof(int)); // what is ntc?
int barr[ntc][ntc]; // what is ntc?
int *nc=(int *)malloc(ntc*sizeof(int)); // what is ntc?
int carr[ntc][ntc]; // what is ntc?
scanf("%d",&ntc); // input -> test case // oh
C cannot see into the future. It is not possible to allocate an array and determine its size later. You need to read ntc first, then use it.
You also need to enable your compiler warnings and make sure all your programs build warning-free. This error can be easily caught by the compiler.
As a side note, automatic variable-length arrays in C are dangerous since they can easily cause your program to overstep its stack size limit. Avoid them. Allocate all arrays of unknown size dynamically.
This program takes as an input the following lines:
23 12 33 19 10 8
5
23 19 8 12 60 18
14 60 12 44 54 10
8 3 12 19 33 10
33 15 7 60 12 10
22 12 19 23 33 11
23 12 33 19 10 8 ( The first line ) are the lottery results.
n ( in this specific case, 5 ) informs how many lines will follow below.
Each line has 6 numbers. The number order doesn't matter.
The rules are: numbers range from 1 to 60 ( including 1 and 60 ) and they never repeat themselves in the same line.
The variable "quadra" stores how many lines have got 4 numbers right.
The variable "quina" stores how many lines have got 5 numbers right.
The variable "sena" stores how many lines have got 6 numbers right.
So, a computer program is running some tests over my code below and it's claiming that it goes wrong for most of them, but I can't see what's the problem here. Does anybody have a clue? Is this code wrong, or is there something wrong with the software that's testing this code?
#include <stdio.h>
int main(){
int mega[6];
int v[50500][6];
int n,swap;
int i,j,k; //counters
int quadra,quina,sena;
quadra = 0;
quina = 0;
sena = 0;
for(i=0;i<6;++i) scanf("%i",&mega[i]); //first line, lottery results
scanf("%i",&n);
for(i=0;i<n;++i){
for(j=0;j<6;++j){
scanf("%i",&v[i][j]);
}
}
for(i=0;i<n;++i){
for(j=0;j<6;++j){
for(k=0;k<6;++k){
if(v[i][j] == mega[k]){
v[i][j] = 61;
}
}
}
}
//reverse bubble sort
for(i=0;i<n;++i){
for(j=0;j<6;++j){
for(k=j+1;k<6;++k){
if(v[i][j] < v[i][k]){
swap = v[i][k];
v[i][k] = v[i][j];
v[i][j] = swap;
}
}
}
}
for(i=0;i<n;++i){
for(j=0;v[i][j] == 61 && j<6;++j);
if(j == 4) ++quadra;
else if(j == 5) ++quina;
else if(j == 6) ++sena;
}
return 0;
}
Your code is true, I understood and tried the flow of it. Looks fine but if you dont need to sort everyline (and use j as a counter in this loop for(j=0;v[i][j] == 61 && j<6;++j); ), you can use simpler ifstatements to compare real lottery results with the ones that entered. What I mean is that your algorithm is a little complex. Try a simple one and see how it works.
Yes, there are a couple of noteworthy issues with your code:
Compile time indicates possibility of uninitialized variable:
But, run-time results in fatal run-time at unknown source location. Stack overflow. It is likely due to this line:
int v[50500][6];
Increase your stack size. It needs to be about 2.5Mbytes for v alone.
Also, this line may not be what you intended:
for(i=0;i<6;++i) scanf("%i",&mega[i]); //first line, lottery results
^
If you meant to loop around the remainder of the code, remove the ; after the for() statement, and use curly braces:
for(i=0;i<6;++i) scanf("%i",&mega[i]) //first line, lottery results
{
scanf("%i",&n);
....
Here's a small C program that prints (well, supposed to print) the real and effective IDs of a process when the file has the setuid flag set. In this program, when I call getpwuid a second time (L.No 38), it tends to overwrite the value of the variable realUserName that was obtained in L.No 24. I'm unable to explain this behavior. Is this the expected behavior and why? I'm trying this in a Linux box (RHEL 2.6.18-371.1.2.el5).
1 /* Filename: test.c
2 * Notes:
3 * 1] ./test owned by user cadmn (userID: 3585)
4 * 2] ./test run by user pmn (4471)
5 * 3] ./test has the setuid bit switched-on.
6 */
7 #include <stdio.h>
8 #include <pwd.h>
9 #include <sys/types.h>
10 #include <unistd.h>
11 int main()
12 {
13
14 uid_t realId, effectiveId;
15 struct passwd *realUser, *effUser;
16
17 realId = getuid(); // realId = 4471
18 effectiveId = geteuid(); //effectiveId = 3585
19
20 printf("Real ID is %i and Effective ID is %i\n", (int)realId, (int)effectiveId);
21 //prints 4472 and 3585, respectively
22
23 realUser = getpwuid(realId);
24 char *realUserName = realUser->pw_name; //realUserName = pmn
25
26 printf("Real ID (name) at this point is %s\n", realUserName);
27 // prints pmn.
28
29 /*
30 *********************************************************
31 * *
32 * everything works as expected up to this point *
33 * *
34 *********************************************************
35 */
36
37 // The value obtained from this call is not used anywhere in this program
38 effUser = getpwuid(effectiveId);
39 printf("\nCalled getpwuid with the effectiveId\n\n");
40
41 printf("Real ID is %i and Effective ID is %i\n", (int)realId, (int)effectiveId);
42 //prints 4472 and 3585, respectively
43
44 printf("Real ID (name) at this point is %s.\n", realUserName);
45 // Expect to still see 'pmn' printed; though see 'cadmn' as the output!
46 // Why does this happen?
47
48 return 0;
49 }
50
Output:
pmn#rhel /tmp/temp > id pmn
uid=4471(pmn) gid=1000(nusers) groups=1000(nusers)
pmn#rhel /tmp/temp >
pmn#rhel /tmp/temp > id cadmn
uid=3585(cadmn) gid=401(cusers) groups=401(cusers)
pmn#rhel /tmp/temp >
pmn#rhel /tmp/temp > ls -l ./test
-r-sr-xr-x 1 cadmn cusers 9377 Dec 24 19:48 ./test
pmn#rhel /tmp/temp >
pmn#rhel /tmp/temp > ./test
Real ID is 4471 and Effective ID is 3585
Real ID (name) at this point is pmn
Called getpwuid with the effectiveId
Real ID is 4471 and Effective ID is 3585
Real ID (name) at this point is cadmn.
pmn#rhel /tmp/temp >
The behaviour you observe is the expected one.
The structure referenced by the return value of getpwuid() is defined statically internal to the latter, so it is expected to be filled (and with this overwritten) for each call to getpwuid().
This line
char * realUserName = realUser->pw_name;
just stores a reference to a value held by this statically internal structure. This value is also overwritten if the statically internal structure is overwritten by the next call to getpwuid().
To get around this there are two possibilities:
Use te reentrant version of getpwuid() which is getpwuid_r(). To be able to use it, add
#define _POSIX_SOURCE
before the very 1st #include statement in your program's sources.
Create copy of the members you need, pw_namein this case. The can be achieved by for example doing:
char * realUserName = strdup(realUser->pw_name);
Be awre that realUserName is now pointing to dynamically allocated memory, which needs to be free()ed by the program itself if not need anymore. To do so call
free(realUserName);
I'm having a hard time using sscanf to scan hour and minutes from a list. Below is a small snip of the list.
1704 86 2:30p 5:50p Daily
1711 17 10:40a 2:15p 5
1712 86 3:10p 6:30p 1
1731 48 6:25a 9:30a 156
1732 100 10:15a 1:30p Daily
1733 6 2:15p 3:39p Daily
I've tried this, but it keeps getting me segmentation Fault.(I'm putting this information into structures).
for(i=0;i<check_enter;i++){
sscanf(all_flights[i],
"%d %d %d:%d%c %d:%d%c %s",
&all_flights_divid[1].flight_number,
&all_flights_divid[i].route_id,
&all_flights_divid[i].departure_time_hour,
&all_flights_divid[i].departure_time_minute,
&all_flights_divid[i].departure_time_format,
&all_flights_divid[i].arrival_time_minute,
&all_flights_divid[i].arrival_time_minute,
&all_flights_divid[i].arrival_time_format,
&all_flights_divid[i].frequency);
printf("%d ",all_flights_divid[i].flight_number);
printf("%d ",all_flights_divid[i].route_id);
printf("%d ",all_flights_divid[i].departure_time_hour);
printf("%d ",all_flights_divid[i].departure_time_minute);
printf("%c ",all_flights_divid[i].departure_time_format);
printf("%d ",all_flights_divid[i].arrival_time_hour);
printf("%d ",all_flights_divid[i].arrival_time_minute);
printf("%c ",all_flights_divid[i].arrival_time_format);
printf("%s\n",all_flights_divid[i].frequency);
}
This is how I declared it.
struct all_flights{
int flight_number;
int route_id;
int departure_time_hour;
int departure_time_minute;
char departure_time_format;
int arrival_time_hour;
int arrival_time_minute;
char arrival_time_format;
char frequency[10];
};
struct all_flights all_flights_divid[3000];
These are the results I get
0 86 2 30 p 0 50 p Daily
0 17 10 40 a 0 15 p 5
0 86 3 10 p 0 30 p 1
0 48 6 25 a 0 30 a 156
0 100 10 15 a 0 30 p Daily
0 6 2 15 p 0 39 p Daily
Look carefully at your list of output targets in sscanf. Do you see the difference between &all_flights_divid[i].departure_time_minute and all_flights_divid[i].departure_time_format? Similary for .arrival_time_format and .frequency.
What do you think the & ampersand is for? Hint: what is one way of returning multiple values from a single function call, and what does this have to do with the & ampersand?
A segmentation fault arises when your program tries to write data into memory the operating system has never instructed the CPU to make available to the program. Segmentation faults do not always occur when data is misplaced, because sometimes data is misplaced within available memory. By way of analogy, if you inadvertently put a book in the wrong place on the bookshelf, you'll not easily find the book later, but the book is still on a bookshelf and does not seem to anyone to be out of place. On the other hand, if you inadvertently put the same book in the refrigerator, well, when mother goes to get the milk she's going to issue you a segmentation fault! That's the analogy, anyway.
In general, it is hard to guess whether misplacing data will cause a segmentation fault (as misplaced into the refrigerator) or not (as misplaced on the bookshelf) until you run the program. The segmentation fault (refrigerator) is preferable because it makes the mistake obvious, so the operating system tries to give you as many segmentation faults as it can by affording the program as little memory as possible.
I am avoiding giving a 100 percent direct answer because of your "homework" tag. See if you cannot figure out the & ampersand matter, then come back here if it still does not make sense.
Your pointers are all messed up. Perhaps a series of local variables specifically for reading this stuff in would help you organize this all in your head.
int flightNum, routeID, depHour, depMin, arrHour, arrMin;
char depFormat, arrFormat;
char * freq;
for(i=0;i<check_enter;i++){
sscanf(
all_flights[i],"%d %d %d:%d%c %d:%d%c %s"
&flightNum, &routeID,
&depHour, &depMin, &depFormat,
&arrHour, $arrMin, $arrFormat,
freq
);
all_flights_divid[i].flight_number = flightNum;
all_flights_divid[i].route_id = routeID;
all_flights_divid[i].departure_time_hour = depHour;
all_flights_divid[i].departure_time_minute = depMin;
all_flights_divid[i].departure_time_format = depFormat;
all_flights_divid[i].arrival_time_hour = arrHour;
all_flights_divid[i].arrival_time_minute = arrMin;
all_flights_divid[i].arrival_time_format = arrFormat;
strcpy(all_flights_divid[i].frequency, freq);
}