Segmentation fault - weird debugging with gdb - c

I'm working in C, Linux terminal. I need to find a pattern in a text and recolor it. GDB debugging can locate the function that is causing the problem via (gdb) backtrace, but it shows me a terrible message when I try to find the exact line:
Error
Program received signal SIGSEGV, Segmentation fault.
strstr_sse2_unaligned ()
at ../sysdeps/x86_64/multiarch/strstr-sse2-unaligned.S:40
40 ../sysdeps/x86_64/multiarch/strstr-sse2-unaligned.S: No such file or dir
ectory.
(gbd)
The broken function is find_and_recolor:
char* my_replace(char *text, char* replacement)
{
int lgreplacement = strlen(replacement);
int lgtext = strlen(text);
char *aux = (char*)malloc((lgreplacement + lgtext + 10) * sizeof(char));
strcpy(aux, replacement);
strcat(aux, text);
return(aux);
}
char* find_and_recolor(char* text, char* pattern)
{
int lgpattern = strlen(pattern);
int lgreplace = lgpattern + 10;//there are exactly 10 characters that must be inserted along the pattern word
int dif = 0;
char *p;
char *replacement = (char*)malloc(lgreplace * sizeof(char));
strcpy(replacement, "\e[0;31m");
strcat(replacement, pattern);
strcat(replacement, "\e[m");//to recolor a word in red, that word must be surrounded by those characters
while(p = strstr(text + dif, pattern))
{
p = my_replace(p, replacement);
p += lgreplace;
dif = p - text;
}
free(replacement);
return strdup(text);
}

it shows me a terrible message when I try to find the exact line:
There is nothing terrible, weird or unusual about this message, you just need to learn proper debugging technique.
What's happening is that the segmentation fault doesn't happen in your code, it happens inside GLIBC code (inside strstr), because you called strstr with bad arguments.
To find which call to strstr that was, use GDB up command to step out of GLIBC code, and into your code. Once you are inside find_and_recolor, you would be able to see the exact line, and print values of text, dif and pattern which caused your crash (assuming you compiled your code for debugging, i.e. with the -g flag).

Updating diff to p-text in while loop where both pointer points to different array doesn't make sense. It is undefined behavior.
Also code has other issues.
Uninitialized variable.
Less optimized as number of call can be reduced.

Related

Segmentation fault in c (C90), Whats the problem?

Heres my main.c:
int main() {
char *x = "add r3,r5";
char *t;
char **end;
t = getFirstTok(x,end);
printf("%s",t);
}
And the function getFirstTok:
/* getFirstTok function returns a pointer to the start of the first token. */
/* Also makes *endOfTok (if it's not NULL) to point at the last char after the token. */
char *getFirstTok(char *str, char **endOfTok)
{
char *tokStart = str;
char *tokEnd = NULL;
/* Trim the start */
trimLeftStr(&tokStart);
/* Find the end of the first word */
tokEnd = tokStart;
while (*tokEnd != '\0' && !isspace(*tokEnd))
{
tokEnd++;
}
/* Add \0 at the end if needed */
if (*tokEnd != '\0')
{
*tokEnd = '\0';
tokEnd++;
}
/* Make *endOfTok (if it's not NULL) to point at the last char after the token */
if (endOfTok)
{
*endOfTok = tokEnd;
}
return tokStart;
}
Why do i get segmentation fault running this main program?
I'm programming a two pass aseembler and i need a function that get parse a string by a delimiter, In this case a white space. Is it better to use strtok instead for this purpose?
I need a command pasrer - So that it will extract "add", an operand parser (By , delimiter), To extract "r3" and "r5". I wanted to check if this getFirstTok function is good for this purpose but when i try to run it i get a segmentation fault:
Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
Thank you.
As pointed out in the comments, string literals are read-only, as they are baked into the compiled program. If you don't want to go with the suggested solution of making your "source program" a stack-allocated array of characters (char x[] = "add r3,r5"), you can use a function like strdup(3) to make a readable/writable copy like so:
#include <string.h>
[...]
char *rw_code = strdup(x);
t = getFirstTok(rw_code, end);
printf("%s", t);
free(rw_code); /* NOTE: invalidates _all_ references pointing at it! */
[...]
And as a little aside, I always make string literals constant const char *lit = "...", as the compiler will usually warn me if I attempt to write to them later on.

Segmentation fault while function call

I got a struct Chat
struct Chat
{
int m_FD;
int m_BindPort;
char m_NameLength;
char* m_Name;
char m_PeerCount;
char** m_PeerList;
} typedef Chat_t;
i'm initializing it with this function:
int chat_init(Chat_t* this, unsigned int nameLen, char* name, unsigned short int bindPort, unsigned int peerCount, char** peerList)
{
this->m_NameLength = nameLen;
this->m_Name = malloc(sizeof(char) * (nameLen+1));
strcpy(this->m_Name, name);
this->m_BindPort = bindPort;
this->m_PeerCount = peerCount;
this->m_PeerList = malloc(sizeof(char*) * peerCount);
for(int i=0; i<peerCount; i++)
{
this->m_PeerList[i] = malloc(sizeof(char) * 16); // enough for xxx.xxx.xxx.xxx\0
strcpy(this->m_PeerList[i], peerList[i]);
}
//Socket initialization for TCP connection...
//Commenting this out doesn't change anything so i'm hiding it for simplification
return 0;
}
After that i'm calling a second function
int chat_communicate(Chat_t* this)
{
printf("2\n");
fflush(stdout);
//Some stuff that doesn't matter because it isn't even called
return retVar;
}
in main like this
void main(void)
{
char* peerList[1];
char username[USERNAME_MAX_LEN];
int initRet;
int loopRet;
Chat_t chat;
peerList[0] = "192.168.2.2";
memset(username, 0, USERNAME_MAX_LEN);
printf("Please enter your user name: ");
scanf("%s", username);
username[USERNAME_MAX_LEN-1] = 0;
initRet = chat_init(&chat, strlen(username), username, 1234, 1, peerList);
printf("File Descriptor: %d\n", chat.m_FD);
printf("Binding Port: %d\n", chat.m_BindPort);
printf("Name Length: %d\n", chat.m_NameLength);
printf("Name: %s\n", chat.m_Name);
printf("Peer Count: %d\n", chat.m_PeerCount);
for(int i=0; i< chat.m_PeerCount; i++)
{
printf("Peer[%d]: %s\n", i, chat.m_PeerList[i]);
}
printf("1");
ret = chat_communicate(&chat);
//Even more Stuff that isn't even called
}
My program outputs the following
File Descriptor: 3
Binding Port: 1234
Name Length: 4
Name: User
Peer Count: 1
Peer[0]: 192.168.2.2
1
Segmentation Fault
It compiles without errors or even warnings.
You can also assume that every string is null-Terminated The stuff i replaced with comments itn't that complicated but just too much to show.
Every value inside the struct is printed with printf right before but when passing this very struct per reference the application crashes.
What i want to know is why i'm getting this Segmentation Fault. Since it appeared while calling a function i thought it is some kind of layout problem but i havn't find anything like that.
Addition:
Because some people weren't able to believe me that the code i hid behind "some stuff" comments doesn't change anything i want to state this here once again. This code just contains a tcp socket communication and only performs read-operations. I also am able to reproduce the error mentioned above without this code so please don't get stuck with it. Parts does not influence the object under observation at all.
Among other potential problems,
this->m_PeerList = malloc(sizeof(char)*peerCount);
is clearly wrong.
m_PeerList is a char **, yet you're only allocating peerCount bytes, which only works if a char * pointer is one byte on your system - not likely.
Replace it with something like
this->m_PeerList = malloc(peerCount * sizeof( *( this->m_peerList ) ) );
Note that sizeof( char ) is always one - by definition.
You're not allocating enough memory for the this->m_Name. It should be on more than this if you want it to store the null-terminated string of the name.
That, or we need more information about the peerList.
Now that you have posted an almost complete code, I was able to spot two problems next to each other:
int chat_init(Chat_t* this, unsigned int nameLen, char* name, unsigned short int bindPort, unsigned int peerCount, char** peerList)
{
this->m_NameLength = nameLen;
this->m_Name = malloc(sizeof(char) * (nameLen + 1)); // correct
//< this->m_Name = malloc(sizeof(char) * nameLen); // wrong
strcpy(this->m_Name, name); // correct
//< memcpy(this->m_Name, name, nameLen); // wrong
...
The lines starting with //< is your original code:
Here you don't allocate enough space, you need to account for the NUL terminator:
this->m_Name = malloc(sizeof(char) * nameLen);
And here you don't copy the NUL terminator:
memcpy(this->m_Name, name, nameLen);
You really need to be aware how strings work in C.
Why don't you debug it yourself. If using GCC, compile your code with options -g -O0. Then run it with gdb:
gdb ./a.out
...
(gdb) r
If it crashes do:
(gdb) bt
This will give exactly where it crashes.
Update: There may be potential problems with your code as found by other users. However, memory allocation related issues will not crash your application just on calling function chat_communicate. There could be different reasons for this behaviour ranging from stack overflow to improper compilation. Without seeing the whole code it is very difficult to tell. Best advice is to consider review comments by other users and debug it yourself.

c Print out the letters, which were repeatedly in string [duplicate]

This question already has answers here:
Bad permissions for mapped region [duplicate]
(2 answers)
Closed 9 years ago.
My function should print out letters which are more than once in string. I have no idea why I get an empty output, or my program 'stops working'.
#include <string.h>
#include <stdio.h>
void funkcja3 (char []);
int main()
{
funkcja3("napnapnaaw");
return 0;
}
void funkcja3 (char napis[])
{
int i=0,j;
for(;i<strlen(napis);i++)
{
if((napis[i]>='a')&&(napis[i]<='z'))
{
int n=0;
for(j=i+1;j<strlen(napis);j++)
{
if(napis[i]==napis[j])
{
n++;
napis[j]=' ';
}
}
if(n>0)
{
printf("%c ", napis[i]);
}
}
}
}
You need to pass a modifiable string:
int main()
{
char str[] = "napnapnaaw";
funkcja3(str);
return 0;
}
This is not a direct answer to your question, but if you just want to print out all the non-capital letters that appear more than once in a given string, then you can just use a histogram (symbol-counting) instead:
void funkcja3(char napis[])
{
int histogram['z'-'a'+1] = {0};
for (int i=0; napis[i]!=0; i++)
{
if ('a' <= napis[i] && napis[i] <= 'z')
histogram[napis[i]-'a']++;
}
for (int i=0; i<'z'-'a'+1; i++)
{
if (histogram[i] > 1)
printf("%c ",'a'+i);
}
}
BTW, histogram = the number of occurrences of each symbol in the data.
When I run your program on my machine (Ubuntu, gcc 4.6), I get a segmentation fault and a core dump. Giving the program and the core dump to gdb and doing a backtrace gives
$ gdb a.out core
Core was generated by `/tmp/a.out'.
Program terminated with signal 11, Segmentation fault.
#0 0x00000000004005a2 in funkcja3 (napis=0x40072c "napnapnaaw") at a.c:25
25 napis[j]=' ';
(gdb) bt
bt
#0 0x00000000004005a2 in funkcja3 (napis=0x40072c "napnapnaaw") at a.c:25
#1 0x0000000000400520 in main () at a.c:8
This hint brings me to removing line 25 and running the program again
$ a.out
n a p n a a
which shows all characters, which were repeated somewhere later in the string.
When you call funkcja3, you're calling it with a string literal. This string literal is at a memory location that isn't modifiable, so the call to napid[j] = ' ' should fail (and does so when I copy your example in to visual studio 2013). What you need to do is either A: use std::string (or another string implementation) or B: make a copy of the string in the function, examine it, and then delete the copy when done. Either way, you probably shouldn't be modifying the original string going in to the function. It's generally bad practice to modify objects passed in to a function unless the function absolutely has to do so.
There are some other ways of completing this task as well, such as an array of 26 shorts to hold the counts for each character. Make those counts and then print out any character that has more then 1.

Fgets errors seg fault

Is there any reason that a program, which compiled earlier, should seg fault at a point because of fgets? I changed no code related to it AT ALL. Suddenly I believe it is failing to open the file, but I tested it with the file like fifteen minutes ago.... All I did was add a search function, so I don't understand what the issue is.....
Could it be the server I'm connecting to over PuTTy?
int createarray( int **arrayRef, FILE *fptr){
int size = 0, i;
char rawdata[100];
while (fgets(rawdata, 99, fptr) != NULL){
size++;
}
rewind(fptr);
*arrayRef = malloc(sizeof(int) * size);
for ( i = 0; i < size; i++ ){
fgets(rawdata, 99, fptr);
*(*arrayRef + i) = atoi(rawdata);
}
return size;
}
int main ( int argc, char **argv ) { //main call
// declare variable to hold file
FILE *inFilePtr = fopen(*(argv + 1), "r");
int **aryHold;
int numElements, sortchoice, key, foundindex;
// Call function to create array and return num elements
numElements = createarray(aryHold, inFilePtr);
This is the code that compiled, performed correct, and hasn't been changed since. GDB says there is an error with fgets.
OK, the reason it use to "work" is you were clobbering an unimportant memory location. Changing your code shifted things around and now you are clobbering something important.
You're passing an uninitialized pointer to createarray(). You wanted to do something like:
int* aryHold;
//...
... createarray(&aryHold ...
BTW, many compilers have the ability to catch this kind of error for you. If you haven't already, you might want to see if your compiler has an error checking option that could have saved you hassling with this (and perhaps find some other code that only "works" accidentally).

print concat value of newline("\n") result shows as <?> symbol in C

I have a code below
#include <stdio.h>
int main()
{
char *price_c = "200";
char *s_att = "test ";
int satt=strlen(s_att);
int price_len = strlen(price_c);
int send_attach_len = price_len+satt;
size_t length = send_attach_len +2;
char *concat = malloc(sizeof(char) *length);
snprintf(concat, length, "%s%s%s", s_att, price_c, "\n");
printf("value of concat is %s", concat);
}
when I see the value printed, I have only test 200 , but on some other occasion, I have test 200 < ? > where < ? > is a weird symbol, somehow the new line is not recognised.
But it is very strange because not all the time this weird symbol is shown up..
It just came up randomly. I am using ubuntu 10.04
Can anyone help me to solve this new line problem, so that it shows new line, and not weird symbol. Or maybe I can change the approach to concat the above value so that the new line is rendered correctly, and not showing a weird symbol?
The code looks ok, except for the very important fact that you are missing some headers.
strlen is in <string.h>, and malloc is in <stdlib.h>.
Include those, turn on your compiler warnings (-Wall for GCC), change your main signature to:
int main(void) { }
and actually return an int from it (or compile as C99, std=c99 for GCC), and the problems should go away.

Resources