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

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.

Related

How to return a string from GetOpenFileNameA

This is a function to open a file dialog in Windows and return a string with the file name:
#include <windows.h>
#include <commdlg.h>
#include <string.h>
char* openFileDlg(char FileTypes[]);
char* openFileDlg(char FileTypes[]){
OPENFILENAME ofn;
char szFile[260];
HWND hwnd;
HANDLE hf;
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.lpstrFile = szFile;
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFile);
strcpy(ofn.lpstrFilter,FileTypes);
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
if(GetOpenFileNameA(&ofn)){
char *toReturn;
sprintf(toReturn,"%s",ofn.lpstrFile);
return toReturn;
}
else{
return NULL;
}
}
When I call this function and open a file, the process ends and returns value 3 (which means there is an error). How can I do so that this function returns a string with the path of the selected file?
Edit: I've changed my code to this and it still doesn't work:
#include <windows.h>
#include <commdlg.h>
#include <string.h>
void openFileDlg(char *toReturn[],char FileTypes[]);
void openFileDlg(char *toReturn[],char FileTypes[]){
OPENFILENAME ofn;
/*
Code for the settings of the GetOpenFileNameA, irrelevant in this question.
If you really need to know what's here, look at the code above.
*/
if(GetOpenFileNameA(&ofn)){
strcpy(*toReturn,ofn.lpstrFile);
}
else{
sprintf(*toReturn,"");
}
}
I should also say that if I press the Cancel button in the open file dialog box instead of selecting a file, it works fine. After some tests, I've noticed that it's the line strcpy(*toReturn,ofn.lpstrFile); that causes the error.
The pointer variable toReturn doesn't point anywhere, using it in any way without initializing it (i.e. making it point somewhere valid and big enough) will lead to undefined behavior
You have two solutions really:
Allocate memory dynamically and return a pointer to that. This of course requires the caller to free the memory when done with it.
Have the function take another two arguments: A pointer to a buffer and the length of the buffer. Then copy the string into that buffer, and return a boolean "true" or "false" success/failure status.
I recommend solution number two.
On an unrelated note, there's no need to use the expensive sprintf function in your case, a simple strcpy (or strncpy if you go with the second solution) will do.
You also have to remember in both cases that strings in C have an actual length of one more than e.g. strlen reports, for the terminating '\0' character.
In general, if you want to return a string in C, I'd use one of the following methods:
1) pass in a string buffer for the method to write to:
int openFileDlg(char FileTypes[], char* toReturn, int bufLen) {
/* ... */
snprintf(toReturn, bufLen, /* what you want to print */);
return ERROR; // status-code
}
/* ... */
char errorBuf[80];
int result;
result = openFileDlg(..., errorBuf, sizeof(errorBuf));
2) allocate memory, expect caller to free it:
char* openFileDlg(char FileTypes[]) {
/* ... */
char *toReturn = malloc(/* big enough */);
sprintf(toReturn, /* what you want to print */);
return toReturn;
}
/* ... */
char* error = openFileDlg(...);
if (error) {
/* ... */
free(error);
}
personally, I'd prefer (1) because it's safer. Option (2) is nicer to the API of the function, but has a risk of memory leaks if you forget to free the returned buffer. In a bigger project (especially with multiple people working on it) this is a very real risk.
(I realise this is pretty much the same as Joachim's answer, but his went up as I was writing mine)
You did not allocate memory for your return value. If you know the length of ofn.lpstrFile you could do this:
char *toReturn = malloc( (sizeOfLpstrFile + 1) * sizeof(char)) ;
sprintf(toReturn,"%s",ofn.lpstrFile);
return toReturn;
Still I consider this a bad idea because the calling function will have to free the memory which is not obvious from the interface.

Segfault thrown on one line of code

I am using this library for libgps and having a few issues with it getting it to run properly.
The error from my debugger after it says segfault is:
Cannot find bounds of current function
The line of code throwing this is located in this file, on line 132.
uint8_t checksum= (uint8_t)strtol(strchr(message, '*')+1, NULL, 16);
I don't know the context of this at all, and I dont know why it would / wouldn't throw a segfault.
My code:
#include <stdio.h>
#include <stdlib.h>
#include <gps.h>
#include <math.h>
/*
*
*/
int main(int argc, char** argv) {
// Open
gps_init();
gps_on();
loc_t data;
gps_location(&data);
printf("%lf %lf\n", data.latitude, data.longitude);
return (EXIT_SUCCESS);
}
The function gps_location() takes you into gps.c and from there it runs into serial.c, once it runs:
void serial_readln(char *buffer, int len)
{
char c;
char *b = buffer;
int rx_length = -1;
while(1) {
rx_length = read(uart0_filestream, (void*)(&c), 1);
if (rx_length <= 0) {
//wait for messages
sleep(1);
} else {
if (c == '\n') {
*b++ = '\0';
break;
}
*b++ = c;
}
}
}
On the break it returns to gps.c goes into:
switch (nmea_get_message_type(buffer)) {
which takes it into nmea.c for nmea_get_message_type above.
It then runs the line:
if ((checksum = nmea_valid_checksum(message)) != _EMPTY)
taking it down to: uint8_t checksum= (uint8_t)strtol(strchr(message, '*')+1, NULL, 16); which is where the error is.
What is causing this?
Edit:
uint8_t is defined as: typedef unsigned char uint8_t;
Segmentation fault is not a "thrown exception" per se, it is a hardware-issued problem ("you said go there, but I don't see anything named 'there'").
As for your problem: what happens when strchr() does not find the specified character? I suggest you try it and find out.
The code you are working with is horrible and has no error checking anywhere. So it may go haywire for any unexpected input. This could be a potential security vulnerability too.
To fix this particular instance, change the code to:
if ( !message )
return NMEA_CHECKSUM_ERR; // possibly `exit` or something, this shouldn't happen
char *star = strchr(message, '*');
if ( !star )
return NMEA_CHECKSUM_ERR;
uint8_t checksum = strtol(star, NULL, 16);
The nmea_parse_gpgga and nmea_parse_gprmc also have multiple instances of a similar problem.
These functions might be acceptable if there was a parser or a regexp check that sanitizes the input before calling these functions. However, based on your question (I didn't check the codebase), it seems data is passed directly from read which is inexcusable.
The segfaulting function was not designed to handle an empty message or in fact any message not matching the expected form.
Another disastrous blunder is that the serial_readln function never checks that it does not write beyond len.

Explanation of missing prototype error message for custom getln function in C

#include <stdio.h>
#include <stdlib.h>
#include <reg51.h>
void main (void) {
SCON = 0x52; // serial port configuration
TMOD = 0x20;
TCON = 0x40;
TH1 = 0xf3; // 2403 baudrate #12mhz
printf("Hello World");
printf("Please enter some text: ");
scanf(getLine());
}
const char *getLine()
{
char *line = NULL, *tmp = NULL;
size_t size = 0, index = 0;
int ch = EOF;
while (ch) {
ch = getc(stdin);
if (ch == EOF || ch == '\n')
ch = 0;
if (size <= index) {
size += CHUNK;
tmp = realloc(line, size);
if (!tmp) {
free(line);
line = NULL;
break;
}
line = tmp;
}
line[index++] = ch;
}
return line;
}
free(str);
That's my code. I think I'm calling getln incorrectly. Is there a way to have the function accept input I can pass in from the user?
This compiler is an evaluation version but I believe it contains the libraries I need.
My goal is to accept a "string", or rather an array of chars and then manipulate its order as a skill test. I only have 2000 KB of memory available to write this.
I'm a bit of a novice when it comes to pointers and not being able to reference. Help or even just explanations are much appreciated.
I'm using a KEIL compiler.
When I select Program>Rebuilt All Target Files to check my errors I receive the following:
assembling STARTUP.A51... assembling XBANKING.A51... compiling
Main.c... MAIN.C(14): warning C206: 'getln': missing
function-prototype MAIN.C(14): error C214: illegal pointer conversion
Target not created
Thank you,
You need to add:
const char *getLine(void);
at the top, below the includes.
This is called a function prototype, and it needs to appear in your source file before the function is used.
You're basically telling the compiler in advance that getLine is a function that takes no arguments and returns const char *. So even though the compiler hasn't seen the definition of the function yet, it can still verify that it's being used correctly when it appears in your main function.
Otherwise the compiler has no idea what getLine is when it hits line 14, and gives an error.
You have correctly defined the function at the bottom, but the C compiler needs a list of functions, called prototypes, at the top. The prototype must include the function type, function name, and any arguments the function takes. For example:
#include <stdio.h>
void hello_world(); //This is the function prototype
int main()
{
hello_world();
}
void hello_world() //You did this part correctly, but C needs the
{ //prototype at the top in order to see this as a
printf("Hello, world!\n"); //defined function
}
In your case, the prototype would simply be:
const char *getLine(void);
and then your program would run without any prototype errors.
Cheers!
Alternatively, if you want to avoid defining the function prototype, define the getLine before main, like
#include ...
const char * getLine() {
...
}
int main() {
...
}

Accessing the 'strdup' of a static array from a different file

I use the get_sessionid() function below from a thread function and then try to free that pointer.
static char sessionid[SESSIONID_LEN] = { '\0' };
static void generate_sessionid() {
char set[] = "0123456789"
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int len;
memset(sessionid, 0, sizeof(char) * SESSIONID_LEN);
for (len = 0; len < SESSIONID_LEN; len++) {
size_t index = (double) rand()/RAND_MAX*(sizeof(set) - 1);
sessionid[len] = set[index];
}
}
char *get_sessionid() {
if (strlen(sessionid) == 0) generate_sessionid();
return strdup(sessionid);
}
When I debug into the thread function from which I call the above get_sessionid, I noticed that the session id returned is not NULL, but the program crashes with SIGABRT immediately when I try to free that pointer. I don't double free the pointer either which can raise an abort signal. I am not sure if thread safety is an issue here.
Also the thread function is defined in a different file.
Edit:
I made the change as was suggested:
static char sessionid[SESSIONID_LEN+1] = { '\0' };
I still get SIGABRT after this edit.
Another thing to mention: I don't get this signal on other machines that I have but only on 1 particular machine that runs Debian Squeeze (Linux kernel: 2.6.32-5-amd64)
Edit 2:
From a different thread function, a segmentation fault is thrown when trying to access the pointer returned by get_sessionid(): SIGSEGV. This error is thrown on all the machines (unlike the previous error) and is reproducible.
And when I debug and try to print the value of the returned pointer in the calling thread function, I get:
<Address 0xfffffffffc005080 out of bounds>
You should define sessionid as
static char sessionid[SESSIONID_LEN+1] = { '\0' };
Then after
for (len = 0; len < SESSIONID_LEN; len++) {
sessionid still a valid C string (a sequence of characters and a '\0'), which is required by strdup().

Why does segmentation fault (core dumped) error apply to my C program?

I keep getting this error and I am not sure how it applies to my program. This is my program.
#include<stdio.h>
#include<stdlib.h>
int nextword(char *str);
void main(void)
{
char *str = "Hello! Today is a beautiful day!!\t\n";
int i = nextword(str);
while(i != -1)
{
printf("%s\n",&(str[i]));
i = nextword(NULL);
}
}
int nextword(char *str)
{
// create two static variables - these stay around across calls
static char *s;
static int nextindex;
int thisindex;
// reset the static variables
if (str != NULL)
{
s = str;
thisindex = 0;
// TODO: advance this index past any leading spaces
while (s[thisindex]=='\n' || s[thisindex]=='\t' || s[thisindex]==' ' )
thisindex++;
}
else
{
// set the return value to be the nextindex
thisindex = nextindex;
}
// if we aren't done with the string...
if (thisindex != -1)
{
nextindex = thisindex;
// TODO: two things
// 1: place a '\0' after the current word
// 2: advance nextindex to the beginning
// of the next word
while (s[nextindex] != ' ' || s[nextindex] != '\n' || s[nextindex] != '\t')
{
if ( s[nextindex] == '\0')
return -1;
else
{
nextindex++;
if (s[nextindex]==' '||s[nextindex]=='\n'||s[nextindex]=='\t')
str[nextindex]='\0';
}
}
}
return thisindex;
}
My program is supposed to have an output to the console of
Hello!
Today
is
a
beautiful
day!!
You are trying to change a String literal. This results in undefined behavior, such as a segfault.
str[nextindex]='\0'
and in Here, str is the parameter of nextWord(), which is:
char *str = "Hello! Today is a beautiful day!!\t\n";
int i = nextword(str);
Since "Hello! Today is a beautiful day!!\t\n" is a string literal - changing it is udnefined behavior, and in your case (luckily) it caused a seg-fault.
You should compile with all warnings and debugging info enabled (if using GCC e.g. on Linux, that means compiling with gcc -Wall -g).
Then you should learn how to use the debugger (i.e. gdb on Linux) and possibly a leak detector like valgrind
a segmentation fault may happen if you dereference some "bad" pointer, e.g. a NULL one or an uninitialized one. It also may happen if you write into a read-only segment (you are probably overwriting a string literal which is put into a read-only -so called .text or .rodata- segment)
Taking account of every warning of the compiler (and enabling them) and using a debugger are essential skills of any C programmer.
Please give nextindex a initial value

Resources