#include <stdio.h>
int main(void)
{
/* an array with 5 rows and 2 columns*/
char* a[5][2];
int y, p;
for(y = 0; y < 5; y++)
{
for(p = 0; p < 2; p++)
{
scanf("%s", a[y][p]);
}
}
int i, j;
/* output each array element's value */
for ( i = 0; i < 5; i++ )
{
for ( j = 0; j < 2; j++ )
{
printf("a[%d][%d] = %s\n", i,j, a[i][j] );
}
}
return 0;
}
I've been getting a Segmentation fault as an output of this program after inserting 2 strings. Can anyone tell me what's wrong with my code?
Problem:
You're declaring 10 uninitialized pointers here:
char* a[5][2];
And then trying to fill them with data:
scanf("%s", a[y][p]);
This is wrong. You need to allocate memory before copying data.
Solution:
I would do this in a more sexy way, but the quick solution would be:
#define MAX_LEN 100
char a[5][2][MAX_LEN];
/* ... */
scanf("%s", a[y][p][0]);
Just a hint on helping troubleshoot. Hope this will help the future readers who are new to pointers.
A better way to troubleshoot a segmentation fault is to run it with a debugger like gdb.
e.g
Compile your program with gdb (You need gdb installed on your host)
gcc -ggdb Test.c -o Test
Then run it with gdb
gdb ./Test
In your case, you will see an output like this. It'll go to the gdb prompt.
Then type run or r, it will run the program. Then it asks for an input. Type your input value. Then the segmentation fault occurs. Now you can see your backtrace by typing backtrace or bt. You can see which line causes your crash. You can see the code by list. You can go to any line by typeing list <line>. Go through a GDB Guide to find out more commands.
It tries to access a pointer, probably invalid that's why it crashes. Then find out why it's invalid. Probably you didn't initialize it or didn't allocate memory. So the easiest fix would be to declare it as an array (rather than a pointer array) like #Andrewjs mentioned in his answer.
Reading symbols from /tmp/Examples/Test...done.
(gdb) run
Starting program: /tmp/Examples/Test
for 1
for 2
10
Program received signal SIGSEGV, Segmentation fault.
0x005c5c3d in _IO_vfscanf_internal (s=0x6d1420, format=0x804867e "%s", argptr=0xbfffe984 "\020\204\004\b", errp=0x0) at vfscanf.c:840
840 *str++ = c;
(gdb) backtrace
#0 0x005c5c3d in _IO_vfscanf_internal (s=0x6d1420, format=0x804867e "%s", argptr=0xbfffe984 "\020\204\004\b", errp=0x0) at vfscanf.c:840
#1 0x005cebbb in __scanf (format=0x804867e "%s") at scanf.c:35
#2 0x0804850d in main () at Test.c:16 <-- Your program's last call
(gdb) list
835 }
836 #else
837 /* This is easy. */
838 if (!(flags & SUPPRESS))
839 {
840 *str++ = c; <-- Crash point
841 if ((flags & MALLOC)
842 && (char *) str == *strptr + strsize)
843 {
844 /* Enlarge the buffer. */
(gdb)
For advance debugging of applications This may help
Related
I have this problem that strtol doesn't work and results in my C program crashing. I am using a Raspberry Pi 3 b+ but that probably doesn't matter.
My program (which is a command line tool to control shift registers) uses strtol for parsing through the command line arguments the program gets.
Here's the output I get: fish: Job 2, “./a.out -p 16 -w 0xff” terminated by signal SIGSEGV (Addroundary error)
And here's the output on gdp:
Program received signal SIGSEGV, Segmentation fault.
__GI_____strtol_l_internal (
nptr=0x76f72968 <_nl_C_LC_CTYPE_toupper+512> "",
nptr#entry=0x7efff6e9 "16", endptr=0x7efff6e9,
base=<optimized out>, group=group#entry=0,
loc=0x76fa1c70 <_nl_global_locale>) at strtol_l.c:484
484 strtol_l.c: No such file or directory.
The following is the code:
else if(!strcmp(argv[arg], "-p") || !strcmp(argv[arg], "-pins")) {
if(argc <= arg+1)
return 1;
pins = strtol(argv[++arg], endptr, 0);
}
The command line argument parsing happens like so:
uint8_t arg, pins;
char **endptr;
uint64_t writeValue;
bool valueGiven; // The other bools that I define are irrelevant
for(arg = 1; arg < argc; arg++) {
if(!strcmp(argv[arg], "-w") || !strcmp(argv[arg], "-write")) {
if(argc <= arg+1)
return 1;
writeValue = strtol(argv[++arg], endptr, 0); // error happens here too
valueGiven = true;
}
else if(!strcmp(argv[arg], "-p") || !strcmp(argv[arg], "-pins")) {
if(argc <= arg+1)
return 1;
pins = strtol(argv[++arg], endptr, 0);
}
// There are more arguments but those are irrelevant
}
And I run the program like this: ./a.out -p 16 -w 0xFF
This error is very odd for the exact same thing worked before, could this be a case of data corruption?
Your char **endptr is uninitialized. It needs to point to a char * where the address of the first unconverted character will be stored. Instead, yours points nowhere, so strtol is going to try to write to whatever bogus memory location it points to, and very likely crash.
GCC and clang should both issue warnings about the uninitialized variable if you enable -Wall. Example. Always use compiler warnings, and don't ignore them!
Normally you would declare a char * variable and pass its address:
char *end;
strtol(argv[++arg], &end, 0);
When I debug my program with lldb, I set a breakpoint in the main function, why did it end directly? In addition, the terminal should wait for my input ...
func.c
#include "func.h"
void insert_head(pnode *phead,pnode *ptail,int i){
pnode pnew = (pnode)calloc(1,sizeof(node));
pnew->num = i;
if(phead == NULL){
*phead = pnew;
*ptail = pnew;
}else{
pnew->pnext = *phead;
*phead = pnew;
}
}
void print_list(pnode phead){
while(phead){
printf("%d",phead->num);
phead=phead->pnext;
}
}
main.cpp
#include "func.h"
int main()
{
pnode phead,ptail;//create new head ptial point to sturct
phead = ptail = NULL;
int i;
while(scanf("%d",&i) != EOF){
insert_head(&phead,&ptail,i);
}
print_list(phead);
return 0;
}
func.h
#pragma once
#include <cstdio>
#include <cstdlib>
//定义结构体
typedef struct Node{
int num;
struct Node *pnext;
}node,*pnode;
//头插法
void insert_head(pnode *phead,pnode *ptail,int i);
void print_list(pnode phead);
You can see the image , i want to figure out this,pls help me , thanks guys
In the example shown above, first of all, it looks like you didn't build your code with debug information (pass -g to your compiler invocations, and make sure you aren't stripping your binary). That's why when you hit your breakpoint at main, you only see some disassembly and not your source code.
If you had debug info, then when your program hit the breakpoint at main, lldb would show you that you are stopped at the beginning of main, before your program has called scanf to query for input. You should just be able to issue the continue command in lldb, and your program will proceed to the scanf call and wait for you input.
For instance, this (admittedly horrible code) works under lldb:
> cat scant.c
#include <stdio.h>
int
main()
{
int i;
int buffer[2000];
int idx = 0;
while(scanf("%d", &i) != EOF) {
buffer[idx++] = i;
}
for(i = 0; i < idx; i++)
printf("%d: %d\n", i, buffer[i]);
return 0;
}
> clang -g -O0 scanit.c -o scanit
> lldb scanit
(lldb) target create "scanit"
Current executable set to '/tmp/scanit' (x86_64).
(lldb) break set -n main
Breakpoint 1: where = scanit`main + 41 at scanit.c:8:7, address = 0x0000000100000e89
(lldb) run
Process 74926 launched: '/tmp/scanit' (x86_64)
Process 74926 stopped
* thread #1 tid = 0x71d134 , queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100000e89 scanit`main at scanit.c:8
5 {
6 int i;
7 int buffer[2000];
-> 8 int idx = 0;
^
9 while(scanf("%d", &i) != EOF) {
10 buffer[idx++] = i;
11 }
Target 0: (scanit) stopped.
(lldb) c
Process 74926 resuming
10 20 30 40 ^D
0: 10
1: 20
2: 30
3: 40
Process 74926 exited with status = 0 (0x00000000)
(lldb)
So that correctly fetched the input from the terminal while the program was running and provided it to the scanf call.
From what I can see, the cause of your confusion is that you didn't build your program with debug information, so when you stopped at your initial breakpoint, you didn't realize you just hadn't gotten to the call to scanf yet.
For your lldb ./test as per excellent #JimIngham remarks lldb can capture user input while the program executes (vs not while being stopped on a breakpoint for instance).
For more complicated programs with terminal UI separate terminal windows (one for lldb, one for your program) might be more convenient.
To use the latter approach either run your ./test program first in terminal where it wait on user input through scanf.
Run another terminal window and launch
lldb -n "test"
Which will attach to the running process based on its name.
Or alternatively you can also attach upon process launch
lldb -n "test" --wait-for
and in another terminal window
./test
This allow you to debug your main and do anything you want with your program (that includes providing user input).
I have a problem writing 8 alphanumeric symbols into my dest_buffer buffer.
I want to convert a char from buff to hexadecimal, then store the value in
different cases of my dest_buffer buffer.
For example:
buff[0] = 58 should give me dest_buffer[0] = '3' and dest_buffer[1] = 'a'
and so on to reach 8 chars.
src is a char[8*sizeof(int)+1] and buff is the same.
Unfortunatly, I only have this output:
2dbb771
*** stack smashing detected ***: ./a.out terminated
[1] 9843 abort (core dumped) ./a.out
This is the loop I use to do the job
for (i = 0; i < 4*sizeof(int); ++i)
{
snprintf (
&dest_buff[i*sizeof(int)*2],
sizeof(int)*2,
"%x",
*(int*)&buff[i * sizeof(int)]
) ;
}
I know I'm missing something but I don't know what, neither where, could
any of you help me?
Thanks
EDIT 1:
Here is another part of my code to be more precise:
int i, rndf ;
char buff[4*sizeof(int)+1];
rndf = open("/dev/urandom", O_RDONLY) ;
if( read (rndf, buff, 4*sizeof(int)) < 0)
{
fprintf (stderr, "%s\n", "An error occured while reading urandom") ;
exit (EXIT_FAILURE) ;
}
close(rndf) ;
after this come the loop
You have stack corruption because char buff[4*sizeof(int)+1]; is your variable.
Let's assume sizeof(int) is 4 bytes. Then variable size is 17 bytes.
By doing this: &dest_buff[i*sizeof(int)*2] you are at some time accessing (when i = 3) address offset 3 * 4 * 2 = 24 which is out of range of your variable.
Conclusion: you have undefined behaviour. Increase variable length or correct you pointer usage.
So I have been writing a handful of C libraries for my own personal use and I have been doing swell until my latest library, which just contains a bunch of string functions. As you can probably tell by the question title, I am getting a SIGSEGV signal. The problem is this: my research indicates that about 99% of all SIGSEGV errors are due to stack overflow, itself due to bad recursion, but as you will see, I am not using any recursion. Furthermore, there are a few odd problems that occur. For one, printf is exhibiting a lot of funky behavior. GDB encounters printf calls but does not actually seem to execute them until a few lines of code later. Likewise, one of my printf statements is being broken up somehow, and only a part is being called, with another part being chopped off apparently.
Here are the key code snippets, some stuff is named funny because I suspected name clashing may be the cause at one point and may have gone a little overboard...
"firstIndexOf" function (finds the first index of a character in a string, if that character is in said string), found at line 31:
int firstIndexOfFUNCTION(char thisChar, char* inThisString)
{
int lengthABC = strlen(inThisString);
printf("\nLength of %s is %d",inThisString,lengthABC);
int thisFunctionsIndex;
for (thisFunctionsIndex=0;thisFunctionsIndex<lengthABC;thisFunctionsIndex++)
{
printf("\n%dth iteration:\n-char 1 is %c\n-char2 is %c",thisFunctionsIndex,inThisString[thisFunctionsIndex],thisChar);
if (inThisString[thisFunctionsIndex] == thisChar)
{
printf("\nMatch found on iteration %d!",thisFunctionsIndex);
return thisFunctionsIndex;
}
}
printf("\nNo matches detected...");
return -3;
}
The "string_functions_test" function (a function just meant to test the other functions) at line 62:
int string_functions_test()
{
printf("PROGRAM INITIALIZED!\n\n");
char* sft_string;
int sft_index;
sft_string = malloc(sizeof(char)*100);
sft_string = "B um sbm. Sbm B bm.";
printf("2nd BREAKPOINT");
sft_index = firstIndexOfFUNCTION('B',sft_string);
sft_string[sft_index] = 'I';
return 0;
}
and last but not least, good ol' main, at line 107:
int main(int argc, char* argv[])
{
string_functions_test();
return 0;
}
Here is the gdb output for a step-through of my code:
(gdb) b 105
Breakpoint 1 at 0x400970: file string_functions.c, line 105.
(gdb) run
Starting program: /home/user/Development/projects/c/string_functions/source/c/a.out
Breakpoint 1, main (argc=1, argv=0x7fffffffde98) at string_functions.c:109
109 string_functions_test();
(gdb) step
string_functions_test () at string_functions.c:64
64 printf("PROGRAM INITIALIZED!\n\n");
(gdb) next
PROGRAM INITIALIZED!
68 sft_string = malloc(sizeof(char)*100);
(gdb) next
69 sft_string = "B um sbm. Sbm B bm.";
(gdb) next
71 printf("2nd BREAKPOINT");
(gdb) next
73 sft_index = firstIndexOfFUNCTION('B',sft_string);
(gdb) step
firstIndexOfFUNCTION (thisChar=66 'B', inThisString=0x400ab9 "B um sbm. Sbm B bm.") at string_functions.c:33
33 int lengthABC = strlen(inThisString);
(gdb) next
34 printf("\nLength of %s is %d",inThisString,lengthABC);
(gdb) next
2nd BREAKPOINT
36 for (thisFunctionsIndex=0;thisFunctionsIndex<lengthABC;thisFunctionsIndex++)
(gdb) next
38 printf("\n%dth iteration:\n-char 1 is %c\n-char2 is %c",thisFunctionsIndex,inThisString[thisFunctionsIndex],thisChar);
(gdb) next
Length of B um sbm. Sbm B bm. is 19
0th iteration:
-char 1 is B
39 if (inThisString[thisFunctionsIndex] == thisChar)
(gdb) next
41 printf("\nMatch found on iteration %d!",thisFunctionsIndex);
(gdb) next
-char2 is B
42 return thisFunctionsIndex;
(gdb) next
47 }
(gdb) next
string_functions_test () at string_functions.c:75
75 sft_string[sft_index] = 'I';
(gdb) next
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400883 in string_functions_test () at string_functions.c:75
75 sft_string[sft_index] = 'I';
(gdb) next
Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.
(gdb) quit
You may notice that the printf which prints "2nd Breakpoint" is called, and then the program steps into a different function before the results are seen. I am assuming this is some whacky behavior on the part of the gcc compiler meant to serve as a cpu optimization, but it is sort of messing me up right now obviously. Likewise, the printf in my for loop is being broken up after the first formatted char. These two things are making it super hard to detect what exactly is happening. Has anyone experienced similar behavior?
In case it matters, I am including:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
You are first pointing the pointer sft_string to what is returned from malloc. In the next line you make it point to a literal string. You need to copy it. A literal is built into the source code and cannot be changed during execution. Otherwise it raises a segment fault, which means that an area of memory that has code is being changed. Use strcpy.
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I've got code that compiles well enough, but when I try to run it, I get a segmentation fault and I can't figure out what's wrong.
The point of the program is to piece together the text of fragmentet ascii art files of varying dimensions and number of fragments.
The fragments are named part_xx-yy where xx is from 00 to 11 and yy is from 00 to 05.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void)
{
int width;
int height;
int xPieces;
int yPieces;
int xTens=0;
int xOnes=0;
int yTens=0;
int yOnes=0;
printf("Fragment width: ");
scanf("%d", &width);
printf("Fragment height: ");
scanf("%d", &height);
printf("Number of fragments on x axis: ");
scanf("%d", &xPieces);
printf("Number of fragments on y axis: ");
scanf("%d", &yPieces);
printf("wtf0");
char *line=malloc(sizeof(width) * sizeof(char));
printf("wtf1");
char array[xPieces][yPieces][height][width];
printf("wtf2");
char fileName[50];
printf("wtf3");
for(int x = 0; x<xPieces;)
{
printf("%d", x);
for(int y = 0; y<yPieces;)
{
printf("%d", y);
if(xOnes>=10)
{
xOnes=0;
xTens++;
}
if(yOnes>=10)
{
yOnes=0;
yTens++;
}
snprintf(fileName, sizeof fileName, "part_%i%i-%i%i", xTens, xOnes, yTens, yOnes);
FILE *file=fopen(fileName, "r");
char buffer[(width) * (height)];
fread(buffer, 1, (width) * (height), file);
for(int i = 0; i<height; i++)
{
printf("%d", i);
for(int j = 0; j<width; j++)
{
printf("%d", j);
array[x][y][i][j] = buffer[j + (i * (width))];
}
}
fclose(file);
y++;
yOnes++;
}
x++;
xOnes++;
}
FILE *newFile=fopen("newFile", "w");
for(int y = 0; y<yPieces; y++)
{
for(int i = 0; i<height; i++)
{
for(int x = 0; x<xPieces; x++)
{
for(int j = 0; j<width; j++)
{
fwrite(&array[x][y][i][j], 1, 1, newFile);
}
}
}
}
fclose(newFile);
free(line);
}
I figured out how to use the debugger, and that indicated there was something wrong with fread(), which I think was caused by my fileName array, but I changed a few things and now all I get from the debugger is this:
Program received signal SIGSEGV, Segmentation fault.
0x0018d68c in fread () from /lib/tls/i686/cmov/libc.so.6
I thought perhaps fread() tried to read into a too small buffer, so I increased the buffer to 10000 (which SHOULD be dramatic overkill), but alas, to no avail.
I have researched quite a bit now, struggling with this problem for a couple of hours, but still have no idea how to go further from here as what I find of similar problems doesn't make much sense to me or isn't similar enough.
I think at this point I need someone else to look at my code, so any help will be greatly appreciated.
.
.
Update: I've updated my code with a few changes, and now I get a segmentation fault here instead:
Program received signal SIGSEGV, Segmentation fault.
0x08049058 in main () at innlev3.c:50
50 *array[x][y][i][j] = buffer[j + (i * (*width))];
I thought this part was pretty good... What have I done wrong, here?
Update 2: Code updated again. I've found something I think is very strange... Neither of those printf's after my scanf's work... Aand I'm back to the good old fread() segmentation fault. I guess it's a good thing I didn't make a new question out of this... :P
Program received signal SIGSEGV, Segmentation fault.
0x0018d68c in fread () from /lib/tls/i686/cmov/libc.so.6
(gdb) backtrace
#0 0x0018d68c in fread () from /lib/tls/i686/cmov/libc.so.6
#1 0x08048fc6 in main ()
I'm guessing file is NULL, probably indicating that *fileName doesn't exist.
Note that statements like this:
fileName[5] = "%i",xTens;
don't do what you probably expected. That statement is equivalent to:
fileName[5] = xTens;
And that should have given you a compiler warning, since you're assigning an int to a char*.
Instead, you probably meant to use snprintf to use printf-style formatting to construct the filename.
char filename[50];
snprintf(filename, sizeof filename, "part_%i%i-%i%", xTens, xOnes, yTens, yOnes);
FILE *file=fopen(fileName, "r");
For your second crash: You have an extra layer of pointers that you don't need on array. Declare it as char array... and remove the * when you access it. As it stands now, you've told the compiler that the elements will be pointers, but you haven't made them point anywhere, and then you asked the compiler to go look where they're pointing using *. Boom!
Your final use of array then needs to make a pointer to each character to pass to fwrite. You'd do that with the & operator, called "address-of", used like &array....
The address-of operator is the opposite of *. Once you have the program working, you can use & other places to simplify your code. For example, instead of declaring int *width and allocating it off the heap using malloc, you can remove the * everywhere and pass &width to scanf.
Since we're back to the fread segfault: Check the return value of fopen before you use it. If it's NULL, print an error message.
if(file == NULL)
{
printf("can't open %s\n", fileName);
exit(1);
}
That will probably tell you what's wrong. However, this isn't debugging code. You should generally check for error returns from the functions you call.
You aren't setting *width to anything before you use it.
You want to do your allocation after you have read the sizes.
printf("fragment width: ");
scanf("%i", width);
printf("fragment height: ");
scanf("%i", height);
char *line=malloc(sizeof(*width) * sizeof(char));
Also, this isn't doing what you think it is:
FILE *file=fopen(*fileName, "r");
It is going to open a file called "p".
And this doesn't do what you think it does either:
fileName[5] = "%i",xTens;
I think you are thinking of python.
+1 for learning to use the debugger :) You're not checking the return value of "fopen". What value of file is being passed to fread?
If you run gdb and backtrace you see this:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7a8a724 in fread () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) backtrace
#0 0x00007ffff7a8a724 in fread () from /lib/x86_64-linux-gnu/libc.so.6
#1 0x0000000000400ad1 in main ()
it means that you are crashing in fread. Your file variable in fread() seems to be incorrect.