My code works perfectly fine, however when I exit my simpleshell I get a segmentation fault. The final of atexit(final) still gets called and works properly. I think the problem is with the atexit(), because when atexit() is removed from the code I can "exit" (i.e. CNTRL+D) the simpleshell properly. However, restated, once atexit() is inside my code (see below to see where it is), it causes a segmentation fault when I exit (even though "final" executes).
static void final(void) {
flag = 0;
assign6 = fopen(".logfile.txt", "a");
assign62 = fopen(".temp_logger.txt", "r");
while(fgets(test2, sizeof(test2), assign62))
{
fprintf(assign6, test2);
}
fclose(assign6);
fclose(assign62);
remove(".temp_logger.txt");
}
You are not checking the assign62 file pointer for proper fopen and it looks like you are deleting it:
static void final(void) {
flag = 0;
assign6 = fopen(".logfile.txt", "a");
assign62 = fopen(".temp_logger.txt", "r");
if (assign6 && assign62) {
while(fgets(test2, sizeof(test2), assign62))
{
fprintf(assign6, test2);
}
fclose(assign6);
fclose(assign62);
remove(".temp_logger.txt");
}
}
Related
So I'm writing a bill handling system. The data currently sits in a Stack structure that I've written.
I have this partially written function that writes out a report:
void GenerateReport(Bill* bill)
{
PrintBillHeading(bill);
//CallEntry* collatedEntries = CollapseCallStack(bill->callEntries);
//TODO
}
Which works fine as long as I leave the second line commented out. If I uncomment it I get a SIGSEGV fault within the PrintBillHeading() function where indicated below.
void PrintBillHeading(Bill* bill)
{
printf("Big Brother Telecom\n");
printf("Bill Date: %s\n\n",DateTimeToISOString(bill->date));
printf("Contract Holder: %s %s\n", bill->title, bill->name);
printf("Address:\n");
char* addressSeg;
char* addressCpy;
strcpy(addressCpy,bill->address); //This line throws the SIGSEGV
while ((addressSeg = strtok_r(addressCpy,";",&addressCpy)))
{
printf("%s\n\0",addressSeg);
}
}
and for completeness here is my CollapseCallStack() function, this is uncomplete, entirely untested and probably doesn't work.
CallEntry* CollapseCallStack(Stack* calls)
{
int size = calls->topIndex;
CallEntry* collatedSet = malloc(sizeof(CallEntry) * size);
CallEntry* poppedCall;
int curIndex = 0;
while (PopStack(calls,poppedCall))
{
bool found = false;
for (int i = 0; i < size; i++)
{
CallEntry* arrItem = collatedSet + i * sizeof(CallEntry);
if (StringEquals(arrItem->phoneNumber,poppedCall->phoneNumber))
{
found = true;
arrItem->minutes += poppedCall->minutes;
}
}
if (!found)
{
memcpy(collatedSet,poppedCall,sizeof(CallEntry)); //
}
}
}
And the CallEntry struct:
typedef struct{
char* phoneNumber;
int minutes;
DateTime* callDateTime;
} CallEntry;
My question is this: how can a function that hasn't yet been called cause a SIGSEGV fault to be expressed earlier on in a program?
Once I've got past this, I can debug the CollapseCallStack() function myself, although if anyone sees any glaring problems I would appreciate a comment on that.
In function PrintBillHeading(), the statement strcpy(addressCpy,bill->address) uses the value of an uninitialized variable addressCpy. This is undefined behavior. Undefined behavior means that the program may crash in any random place. If the program contains undefined behavior the entire program is invalid.
In addition to the correct answer by AlexP, I'd like to point out another (lurking) undefined behaviour:
void GenerateReport(Bill* bill)
{
PrintBillHeading(bill);
CallEntry* collatedEntries = CollapseCallStack(bill->callEntries);
//TODO
}
Now, CollapseCallStack in your current implementation does not return anything. It will still be called, and actually something will be assigned to your collatedEntries pointer upon your initialization of it.
The problem is that when CollapseCallStack is called, memory for the return value is being allocated, but it never gets assigned a meaningful value, since the return statement is missing. So, essentially your collatedEntries pointer will be initialized with a random garbage value, and if you'd try to dereference it, it would cause UB.
I'm currently using Clion 2017.3.4 in C99.
while trying to run and debug my program, the debugger jumps into 'disassembly view', and I want to know what the problem is.
basically, the function gets a season(type), a input string (season_info), and an index, that points to a different place in the input string.
the function should return the year as an integer, while the input is a string
the disassembly view is showen when I step into the free() line.
any ideas what the problem is?
and generally what the disassembly view means?
int GetSeasonYear(Season season, const char* season_info, int *index){
char* tmp_str = GetStringByLine(season_info, index);
if(tmp_str == NULL){
SeasonDestroy(season);
return 0;
}
season->season_year = atoi(tmp_str);
free(tmp_str);
return 1;
}
this is the function used inside the GetSeasonYear function(although I check and it works fine).
char* GetStringByLine(const char* season_info, int* index){ // change back to static
int i = 0;
while(season_info[i] != '\n'){
i++;
}
char* tmp_str = malloc(sizeof(char)*(i+1));
if(tmp_str == NULL){
return NULL;
}
memcpy(tmp_str, season_info, sizeof(char)*i);
tmp_str[i+1]='\0';
*index = i;
return tmp_str;
}
thanks
You are stepping into a function (free) for which you either
a) Do not have the source for
or
b) have the source for but the debuuger cannot locate it.
free() is a call to the system to release memory. It's more than likely been compiled with high optimisation and without debug symbols, so the best the debugger can do is just show you the disassembled machine code that it's executing.
Basically, it's normal. There's also very little benefit to stepping into calls like that.
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.
I get a pretty weird segmentation fault error when I am trying to use the same function in two different places.
printTVNode function work fine on main.
On Main:
printTVNode(headTVNode); /* Works fine here */
TVNodePointer headTopic = NULL;
TopicEmmissions(&headTopic,headTVNode,desiredTopic);
When I am trying to use printTVNode inside TopicEmmissions function a get Seg Fault.
void TopicEmmissions(TVNodePointer * headTopic,TVNodePointer headTVNode,char * desiredTopic){
TVNodePointer currentTVNode = headTVNode;
EmmissionPointer currentEmmission;
EventPointer currentEvent;
EventPointer topicSubjects = NULL;
int flag,countEvent = 1,countEmmission = 1;
printTVNode(headTVNode); /* Get Segmentation Fault here*/
...
printTVNode function:
void printTVNode(TVNodePointer headTVNode){
TVNodePointer currentTVNode = headTVNode;
while ( currentTVNode != NULL ){
printEmmission(*(currentTVNode->anEmmission));
currentTVNode = currentTVNode->next;
}
}
The problem seems to be in the following line :
printEmmission(*(currentTVNode->anEmmission));
In a situation where anEmmission is NULL, when you try to dereference it, I think you will get a segfault.
Make sure to check that anEmmission is not NULL before doing dereferencing.
I do not know why I get Memory fault (core dumped) when I run this code
if (flg == 4) // PIPE
{
char **cmds;
char ***cmdarg;
int j=0;
cmds = split_str(cmd, "|");
for (i = 0; args[i] != NULL; i++)
{
if (strcmp(args[i], "|") == 1)
{
cmdarg[j][i]=args[i];
}
else
{
cmdarg[j][i+1] = NULL;
j++;
}
printf("%s\n",cmdarg[j][i]);
}
}
I am not so expert with pointers and arrays
cmdarg is not initialized. And I'm sure that GCC, when invoked as gcc -Wall -g, would have warned you about that.
You could keep its length, e.g.
int cmdarglen = 0;
Then initialize it to some suitable default size:
#define INITIAL_CMDARG_SIZE 10
cmdarg = calloc(INITIAL_CMDARG_SIZE, sizeof(*cmdarg));
if (!cmdarg) { perror("calloc cmdarg initial"); exit (EXIT_FAILURE); );
cmdarglen = INITIAL_CMDARG_SIZE;
then grow it when needed, e.g.
if (j >= cmdarglen) {
int newcmdarglen = 5*j/4+10;
char***newcmdarg = calloc(newcmdarglen, sizeof(*cmdarg));
if (!newcmdarg)
{ perror("calloc growing cmdarg"); exit(EXIT_FAILURE); };
memcpy (newcmdarg, cmdarg, sizeof(*cmdarg)*j);
free (cmdarg);
cmdarg = newcmdarg;
}
to be inserted appropriately inside your for loop. Of course, you probably need to initialize each element of cmdarg (by allocating them individually).
Don't forget to free(cmdarg) later.
At last, learn how to use the gdb debugger and valgrind memory leak detector.
You never initialize the cmdarg variable in you code. It will have an unspecified value, so when you dereference it, there is undefined behavior. In your case, this manifest by a segmentation fault.
I don't know what your code is trying to do, but what I can see is that you are reffering to an uninitialized variable 'cmdarg'.Another adivce: when possible (and I think that nearly always it is possible) try to avoid three levels of indirections (***).