memory errors while reading a large file in C - c

I am very novice in working with malloc/realloc in C and so need some help. The following is short snippet of a big program where I intend to read a big (fasta) file almost 80000 line numbers and store the first line marked with > (name) and following line (sequence) in two separate arrays- fasta_name and fasta_seq. I have used a standard library which gives the output as a structure but I need to change it into arrays since later on the program I need to check input provided by the user with each of the fasta entries in the file..
The inputfile format is:
P21306\n
MSAWRKAGISYAAYLNVAAQAIRSSLKTELQTASVLNRSQTDAFYTQYKNGTAASEPTPITK\n
P38077\n
MLSRIVSNNATRSVMCHQAQVGILYKTNPVRTYATLKEVEMRLKSIKNIEKITKTMKIVASTRLSKAEKA\n
=======================
The code is:
KSEQ_INIT(gzFile, gzread) ///EXTERNAL LIBRARY FOR BIOLOGISTS READING FASTA FORMAT FILE///
int main(int argc,char *argv[])
{
char **fasta_name=(char **)malloc(sizeof(char *)*80000);
for(i=0;i<size;i++)
{
fasta_name[i]=(char*)malloc(sizeof(char)*50);
}
char **fasta_seq=(char**)malloc(sizeof(char *)*80000);
for(i=0;i<size;i++)
{
fasta_seq[i]=(char*)malloc(sizeof(char)*5000);
}
fpf = gzopen("fasta_seq_nr_uniprot.txt", "r");
seq = kseq_init(fpf);
while((l = kseq_read(seq)) >= 0)
{
strcpy(fasta_name[index1],seq->name.s);
strcpy(fasta_seq[index1],seq->seq.s);
index1++;
}
kseq_destroy(seq);
gzclose(fpf);
for(i=0;i<size;i++)
{
free(fasta_name[i]);
}
for(i=0;i<size;i++)
{
free(fasta_seq[i]);
}
free(fasta_name);
free(fasta_seq);
The program shows no compilation errors but the following memory errors and segmentation fault using Valgrind.
$ valgrind --track-origins=yes --leak-check=full ./Gwidd_uniprot_map2 xaa==3511== Memcheck, a memory error detector
==3511== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==3511== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
==3511== Command: ./map2 xaa
==3511==
--3511-- ./map2:
--3511-- dSYM directory has wrong UUID; consider using --dsymutil=yes
Opening file xaa
==3511== Use of uninitialised value of size 8
==3511== at 0x100012C43: __strcpy_chk (mc_replace_strmem.c:893)
==3511== by 0x100001A78: __inline_strcpy_chk (in ./map2)
==3511== by 0x10000183E: main (in ./map2)
==3511== Uninitialised value was created by a heap allocation
==3511== at 0x100011345: malloc (vg_replace_malloc.c:236)
==3511== by 0x10000170C: main (in ./map2)
==3511==
==3511== Invalid write of size 1
==3511== at 0x100012C43: __strcpy_chk (mc_replace_strmem.c:893)
==3511== by 0x100001A78: __inline_strcpy_chk (in ./map2)
==3511== by 0x10000183E: main (in ./map2)
==3511== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==3511==
==3511==
==3511== Process terminating with default action of signal 11 (SIGSEGV)
==3511== Access not within mapped region at address 0x0
==3511== at 0x100012C43: __strcpy_chk (mc_replace_strmem.c:893)
==3511== by 0x100001A78: __inline_strcpy_chk (in ./map2)
==3511== by 0x10000183E: main (in ./map2)
==3511== If you believe this happened as a result of a stack
==3511== overflow in your program's main thread (unlikely but
==3511== possible), you can try to increase the size of the
==3511== main thread stack using the --main-stacksize= flag.
==3511== The main thread stack size used in this run was 8388608.
==3511==
==3511== HEAP SUMMARY:
==3511== in use at exit: 6,674,813 bytes in 3,664 blocks
==3511== total heap usage: 3,807 allocs, 143 frees, 6,698,108 bytes allocated
==3511==
==3511== LEAK SUMMARY:
==3511== definitely lost: 0 bytes in 0 blocks
==3511== indirectly lost: 0 bytes in 0 blocks
==3511== possibly lost: 0 bytes in 0 blocks
==3511== still reachable: 6,674,813 bytes in 3,664 blocks
==3511== suppressed: 0 bytes in 0 blocks
==3511== Reachable blocks (those to which a pointer was found) are not shown.
==3511== To see them, rerun with: --leak-check=full --show-reachable=yes
==3511==
==3511== For counts of detected and suppressed errors, rerun with: -v
==3511== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Segmentation fault
CODE EDITED AS:
char **fasta_name=(char **)malloc(sizeof(char *)*80000);
if(fasta_name == NULL)
{
printf("Unable to allocate memory.\n");
exit(EXIT_FAILURE);
}
for(i=0;i<size;i++)
{
fasta_name[i]=(char*)malloc(sizeof(char)*50);
if(fasta_name[i] == NULL)
{
printf("Unable to allocate memory.\n");
exit(EXIT_FAILURE);
}
}
char **fasta_seq=(char**)malloc(sizeof(char *)*80000);
if(fasta_seq == NULL)
{
printf("Unable to allocate memory.\n");
exit(EXIT_FAILURE);
}
for(i=0;i<size;i++)
{
fasta_seq[i]=(char*)malloc(sizeof(char)*5000);
if(fasta_seq[i] == NULL)
{
printf("Unable to allocate memory.\n");
exit(EXIT_FAILURE);
}
}
fpf = gzopen("fasta_seq_nr_uniprot.txt", "r");
seq = kseq_init(fpf);
while((l = kseq_read(seq)) >= 0)
{
strcpy(fasta_name[index1],seq->name.s);
strcpy(fasta_seq[index1],seq->seq.s);
index1++;
}
kseq_destroy(seq);
gzclose(fpf);

Based on the error Access not within mapped region at address, I would say that you are accessing memory that's out of bounds, causing your segmentation fault. Check that malloc() doesn't return NULL to you after calling it, otherwise you risk accessing memory you don't actually own.
Do this after every single malloc() call. For example:
int *i = (int *) malloc(sizeof(int));
if(!i){
fprintf(stderr, "Something went wrong with malloc(), exiting...\n");
exit(1);
}
Another thing to check is to see if index1 is out of bounds of your allocations. I don't see where it's declared or initialized. Is it possible that your allocation for fasta_name and others is too small, given that you read information using a while loop that keeps incrementing the index?

Related

Copying a string - how do I have to deal with memory leaks and error cases?

I am trying to implement the function int *cpy_array(int v[], int size), which copies the array in another and returns the new array as pointer. I also have to watch out for error cases and use dynamic memory.
Ok i know that malloc returns 0 when there is nout enough memory available. I was wondering if there might be any other possible errors as well which I missed out. Then I have to implement free() in the case of succsess as well as in error case.
I tried to implement something like:
if (!w[i]) {
for (k = 0; k < i; ++k)
free(w[k]);
return 0;
}
But there was always an error with this.
In file included from hot.c:2:
C:/mingw-w64/i686-8.1.0-posix-dwarf-rt_v6-rev0/mingw32/i686-w64-mingw32/include/stdlib.h:502:27: note: expected 'void *' but argument is of type 'int'"
void __cdecl free(void *_Memory);
And I am not sure why to free() the new array or should the old array be freed? I tried to free it with pointer in my function, but didnt work either and dont think it should be in the main?
Here is the original code:
int *cpy_array(int v[], int size);
int main(void)
{
int size;
size = 4;
int myArray[4] = {1234};
if (*cpy_array(myArray, size) == 0)
{
printf("No memory available.");
}else{
printf("The new Array: %i", *cpy_array(myArray, size));
}
return 0;
}
int *cpy_array(int v[], int size)
{
int i;
int *a = malloc(size * sizeof(int));
if(*a == 0)
return 0;
for (i = 0; i < size; i++)
{
a[i] = v[i];
}
return a;
}
In your first code snippet, you incorrectly deallocated the array of integers w. You can't free single integers in that array, but what you need to do is simply type in:
free(w);
That will free the entire array.
You can also see from the text of the error - note: expected 'void *' but argument is of type 'int'" void __cdecl free(void *_Memory), that the program expected a pointer to the array and not an integer.
You can't free the old array, because it's statically created and the memory for it allocated at the start of the program and it will be freed at the end of the function in which it was defined by the program itself, so you don't need to worry about that. Whereas it's your job to free the dynamically created arrays such as the one you created through the cpy_array(int v[], int size) function.
More on the difference between static and dynamic allocation, you can look up here:
Difference between static memory allocation and dynamic memory allocation
This part of code, wouldn't proparly print the array (you will just print the first number of the array), and also you are calling the function twice, which is excessive and should be done only once for the same array.
if (*cpy_array(myArray, size) == 0)
{
printf("No memory available.");
}else{
printf("The new Array: %i", *cpy_array(myArray, size));
}
You could easify fix these problems by defining a pointer which could store the return value of the function, so you don't have to call it twice and then to correctly print the array use a for loop:
int * copiedArray = cpy_array(myArray, size);
if (copiedArray == NULL)
{
printf("No memory available.");
}else{
printf("The new Array: ");
for (int i = 0; i < size; i++)
printf("%i ", copiedArray[i]);
}
I noticed that you are checking whether a pointer is pointing to something or not incorrectly. Once in main:
if (*cpy_array(myArray, size) == 0)
And once in the cpy_array(int v[], int size) function:
if(*a == 0)
This will not work because you are dereferencing the pointer and checking whether the value to which it is pointing is zero. What you want to do is check the value of the pointer itself. If that is NULL then the allocation didn't work:
if (cpy_array(myArray, size) == NULL)
and
if(a == NULL)
You should use NULL instead of zero because you are explicitly stating that you are checking a value of a pointer, and NULL may not be equal to zero on every machine.
More on that topic here:
What is the difference between NULL, '\0' and 0
To detect you problems concerning the memory use valgrind, If I do that gives :
==10947== Memcheck, a memory error detector
==10947== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==10947== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==10947== Command: ./a.out
==10947==
==10947== Conditional jump or move depends on uninitialised value(s)
==10947== at 0x10548: cpy_array (c.c:25)
==10947== by 0x104B3: main (c.c:11)
==10947==
==10947== Invalid read of size 4
==10947== at 0x104B8: main (c.c:11)
==10947== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==10947==
==10947==
==10947== Process terminating with default action of signal 11 (SIGSEGV)
==10947== Access not within mapped region at address 0x0
==10947== at 0x104B8: main (c.c:11)
==10947== If you believe this happened as a result of a stack
==10947== overflow in your program's main thread (unlikely but
==10947== possible), you can try to increase the size of the
==10947== main thread stack using the --main-stacksize= flag.
==10947== The main thread stack size used in this run was 8388608.
==10947==
==10947== HEAP SUMMARY:
==10947== in use at exit: 16 bytes in 1 blocks
==10947== total heap usage: 1 allocs, 0 frees, 16 bytes allocated
==10947==
==10947== 16 bytes in 1 blocks are definitely lost in loss record 1 of 1
==10947== at 0x4847568: malloc (vg_replace_malloc.c:299)
==10947== by 0x10533: cpy_array (c.c:24)
==10947== by 0x104B3: main (c.c:11)
==10947==
==10947== LEAK SUMMARY:
==10947== definitely lost: 16 bytes in 1 blocks
==10947== indirectly lost: 0 bytes in 0 blocks
==10947== possibly lost: 0 bytes in 0 blocks
==10947== still reachable: 0 bytes in 0 blocks
==10947== suppressed: 0 bytes in 0 blocks
==10947==
==10947== For counts of detected and suppressed errors, rerun with: -v
==10947== Use --track-origins=yes to see where uninitialised values come from
==10947== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 6 from 3)
The "Conditional jump or move depends on uninitialised value(s)" comes from the *a in if(*a == 0) and "Invalid read of size 4 ..." because you dereference 0 because of the return 0;
after changing if(*a == 0) to if(a == 0) to solve the two previous problems that condition is (a priori) false and _valgrind says :
==11116== Memcheck, a memory error detector
==11116== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==11116== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==11116== Command: ./a.out
==11116==
Mein neuer Array enthaelt folgende Zeichen: 1==11116==
==11116== HEAP SUMMARY:
==11116== in use at exit: 32 bytes in 2 blocks
==11116== total heap usage: 3 allocs, 1 frees, 1,056 bytes allocated
==11116==
==11116== 16 bytes in 1 blocks are definitely lost in loss record 1 of 2
==11116== at 0x4847568: malloc (vg_replace_malloc.c:299)
==11116== by 0x10523: cpy_array (c.c:24)
==11116== by 0x104A3: main (c.c:11)
==11116==
==11116== 16 bytes in 1 blocks are definitely lost in loss record 2 of 2
==11116== at 0x4847568: malloc (vg_replace_malloc.c:299)
==11116== by 0x10523: cpy_array (c.c:24)
==11116== by 0x104CF: main (c.c:15)
==11116==
==11116== LEAK SUMMARY:
==11116== definitely lost: 32 bytes in 2 blocks
==11116== indirectly lost: 0 bytes in 0 blocks
==11116== possibly lost: 0 bytes in 0 blocks
==11116== still reachable: 0 bytes in 0 blocks
==11116== suppressed: 0 bytes in 0 blocks
==11116==
==11116== For counts of detected and suppressed errors, rerun with: -v
==11116== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 6 from 3)
so yes you have memory leaks because you lost 2 times the allocation return by cpy_array
you need to have something like :
int * v = cpy_array(myArray, size);
if (*v == 0)
{
printf("Speicher kann nicht freigegeben werden.");
}else{
printf("Mein neuer Array enthaelt folgende Zeichen: %i",
*v);
}
free(v);
Doing that correction valgrind signals nothing :
valgrind --leak-check=full ./a.out
==11224== Memcheck, a memory error detector
==11224== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==11224== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==11224== Command: ./a.out
==11224==
Mein neuer Array enthaelt folgende Zeichen: 1==11224==
==11224== HEAP SUMMARY:
==11224== in use at exit: 0 bytes in 0 blocks
==11224== total heap usage: 2 allocs, 2 frees, 1,040 bytes allocated
==11224==
==11224== All heap blocks were freed -- no leaks are possible
==11224==
==11224== For counts of detected and suppressed errors, rerun with: -v
==11224== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
I encourage you to
compile with all warning detection, like gcc -g -Wall -pedantic ...
when you have problem use valgrind and/or debugger
even you do not see a problem run anyway under valgrind, so problems can be hidden
this is not the correct way to initialize the array
int myArray[4] = {1234};
write
int myArray[4] = { 1,2,3,4 };
or simply
int myArray[] = { 1,2,3,4 };
Calling the function cpy_array .. when you write
if (*cpy_array(myArray, size) == 0)
Is not correct, why? because what if the function returns NULL, then you are dereferencing NULL
In your function cpy_array you are dereferencing a, that is not correct, instead compare the pointer
if ( a == NULL)
and use the standard constant NULL for a null pointer instead of 0 since it may not be 0 on all platforms.

Segmentation fault - splitting command into tokens

The code I am implementing in which I split the command first by pipes then by spaces.
int main(){
pid_t pid;
while (1) {
printf("$ ");
char *cmd;
ssize_t size=0;
getline(&cmd,&size,stdin);
if (cmd[strlen(cmd)-1]== '\n') {cmd[strlen(cmd)-1]='\0';}
char** commands = splitter(cmd,"|");
int i=0;
int fd[2],in=0;
while (commands[i+1]!=NULL){
pipe(fd);
char **args = splitter(commands[i]," \t");
pid = fork();
if (pid==-1) {exit(EXIT_FAILURE);}
else if (pid==0){
close(fd[0]);
changeIO(in,0);
changeIO(fd[1],1);
execvp(args[0],args);
}
else{
waitpid(pid,NULL,0);
close(fd[1]);
close(in);
in = fd[0];
}
i++;
}
char **args = splitter(commands[i+1]," \t");
changeIO(in,0);
execvp(args[0],args);
}
}
Here follows the implementation of the functions the code above uses
void changeIO(int oldfd,int newfd){
if (oldfd!=newfd){
dup2(oldfd,newfd);
close(oldfd);
}
}
char** splitter(char* stringToSplit, char* delimiter){
char *token;
int initial_size = 300;
char** args = malloc(initial_size*sizeof(char*));
token = strtok(stringToSplit,delimiter);
int index = 0;
while (token != NULL) {
args[index] = token;
index++;
if (index >= initial_size) {
initial_size = initial_size + 100;
args = realloc(args,initial_size*sizeof(char*));
if (!args) exit(EXIT_FAILURE);
}
token = strtok(NULL,delimiter);
}
args[index] = NULL;
return args;
}
Ok executing the code I get a segmentation fault when I enter the command in the user input. Testing various options I came to realize it has something to do with the char** args in which I pass the tokens of each commands. I can't understand why this happens since memory is allocated and from what I understand I just point the pointer args to that allocated memory. Any help appreciated.
EDIT: Checked with valgrind. Results below:
==3361== Memcheck, a memory error detector
==3361== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==3361== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==3361== Command: ./mysh3
==3361==
==3361== Conditional jump or move depends on uninitialised value(s)
==3361== at 0x40AFE97: getdelim (iogetdelim.c:59)
==3361== by 0x40ACDD1: getline (getline.c:32)
==3361== by 0x80486C4: main (in /home/dimitris/Desktop/mysh3)
==3361==
$ ls
==3361== Invalid read of size 1
==3361== at 0x4101CAA: execvpe (execvpe.c:50)
==3361== by 0x4101B33: execvp (execvp.c:26)
==3361== by 0x804885F: main (in /home/dimitris/Desktop/mysh3)
==3361== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==3361==
==3361==
==3361== Process terminating with default action of signal 11 (SIGSEGV)
==3361== Access not within mapped region at address 0x0
==3361== at 0x4101CAA: execvpe (execvpe.c:50)
==3361== by 0x4101B33: execvp (execvp.c:26)
==3361== by 0x804885F: main (in /home/dimitris/Desktop/mysh3)
==3361== If you believe this happened as a result of a stack
==3361== overflow in your program's main thread (unlikely but
==3361== possible), you can try to increase the size of the
==3361== main thread stack using the --main-stacksize= flag.
==3361== The main thread stack size used in this run was 8388608.
==3361==
==3361== HEAP SUMMARY:
==3361== in use at exit: 2,520 bytes in 3 blocks
==3361== total heap usage: 5 allocs, 2 frees, 4,568 bytes allocated
==3361==
==3361== LEAK SUMMARY:
==3361== definitely lost: 0 bytes in 0 blocks
==3361== indirectly lost: 0 bytes in 0 blocks
==3361== possibly lost: 0 bytes in 0 blocks
==3361== still reachable: 2,520 bytes in 3 blocks
==3361== suppressed: 0 bytes in 0 blocks
==3361== Rerun with --leak-check=full to see details of leaked memory
==3361==
==3361== For counts of detected and suppressed errors, rerun with: -v
==3361== Use --track-origins=yes to see where uninitialised values come from
==3361== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Segmentation fault
It's an off-by-one array index.
Your while loop finishes with commands[i+1] being null. Then you pass it to splitter.
Pass commands[i] instead.
When strtok() finds a token, it changes the character immediately after the token into a \0, and then returns a pointer to the token.

How to read stream from STDIN or Unix pipe in C

Forgive my ignorance, I'm brand new to C. As a learning experience, I'm trying to read in an image that's been cat'ed and piped to a simple C script. I'd like to iterate over the octets, and at least for now, just print them to STDOUT.
Example: cat some-image.png | ./my-c-program
Code:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
FILE *input;
input = fopen(argv[1], "r");
int c;
long retvalue = 0;
while (EOF != (c = fgetc(input))) {
retvalue++;
printf("%d", c);
}
printf("length: %ld", retvalue);
return 0;
}
Currently, I'm getting a lot of SegFault 11
I'm not too sure how to make sense of this, but Valgrind tells me:
==90834== Memcheck, a memory error detector
==90834== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==90834== Using Valgrind-3.11.0.SVN and LibVEX; rerun with -h for copyright info
==90834== Command: ./a.out
==90834==
--90834-- ./a.out:
--90834-- dSYM directory is missing; consider using --dsymutil=yes
==90834== Syscall param open(filename) points to unaddressable byte(s)
==90834== at 0x1002FA012: open$NOCANCEL (in /usr/lib/system/libsystem_kernel.dylib)
==90834== by 0x1001EE4B6: fopen (in /usr/lib/system/libsystem_c.dylib)
==90834== by 0x100000EDC: main (in ./a.out)
==90834== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==90834==
==90834== Invalid read of size 8
==90834== at 0x1001ECE07: flockfile (in /usr/lib/system/libsystem_c.dylib)
==90834== by 0x1001ED52E: fgetc (in /usr/lib/system/libsystem_c.dylib)
==90834== by 0x100000EF1: main (in ./a.out)
==90834== Address 0x68 is not stack'd, malloc'd or (recently) free'd
==90834==
==90834==
==90834== Process terminating with default action of signal 11 (SIGSEGV)
==90834== Access not within mapped region at address 0x68
==90834== at 0x1001ECE07: flockfile (in /usr/lib/system/libsystem_c.dylib)
==90834== by 0x1001ED52E: fgetc (in /usr/lib/system/libsystem_c.dylib)
==90834== by 0x100000EF1: main (in ./a.out)
==90834== If you believe this happened as a result of a stack
==90834== overflow in your program's main thread (unlikely but
==90834== possible), you can try to increase the size of the
==90834== main thread stack using the --main-stacksize= flag.
==90834== The main thread stack size used in this run was 8388608.
==90834==
==90834== HEAP SUMMARY:
==90834== in use at exit: 34,916 bytes in 425 blocks
==90834== total heap usage: 505 allocs, 80 frees, 41,044 bytes allocated
==90834==
==90834== LEAK SUMMARY:
==90834== definitely lost: 0 bytes in 0 blocks
==90834== indirectly lost: 0 bytes in 0 blocks
==90834== possibly lost: 0 bytes in 0 blocks
==90834== still reachable: 0 bytes in 0 blocks
==90834== suppressed: 34,916 bytes in 425 blocks
==90834==
==90834== For counts of detected and suppressed errors, rerun with: -v
==90834== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Segmentation fault: 11
Any help or guidance is appreciated.
If you don't provide an argument to ./my-c-program then argv[1] is NULL and you get a segfault.
To read from standard input using the Standard C I/O functions, use one or more of
getchar(), fgetc(stdin), scanf(), fread(..., stdin), fgets(..., stdin)
You do not need to open stdin as the C runtime startup code does that for you. If you need to read from files supplied by arguments, you need to use fopen() first to create a new input stream.

Perhaps a memory issue when I reinitialize an array? [duplicate]

I am running breadth first search and bellman ford algorithms on large sets of graph data in the format (u, v, weight) from an input file.
I initialize in the breadth first search, that all vertex's should be marked 0 for unvisited.
Later in the program, since I am calling BFS after every time I add an edge, rather than at the end of the program all together (it's part of a research project on bellman ford and BFS even though it doesn't quite make sense) I reinitialize the vertex array to unvisited.
However, I am getting a segmentation fault when I run larger sets it seems when I reinitialize the vertex array. I make the assumption about larger sets because I have a few smaller sets of test data going from 8 vertices, to 10, then at 100 and larger it fails.
Here is how I initialize at the very beginning of the program:
for(i=0;i<numberVertices;i++)
{
vertexArray[i].v = i+1;
vertexArray[i].adj = NULL;
vertexArray[i].marked = 0;
if(i==0)
{
vertexArray[i].weight = 0;
}
else{
vertexArray[i].weight = 10000;
}
}
And here is how I reinitialize at the end of a while loop set to break when it reaches the end of the file directly after BFS finishes:
BFS(q, u)
for(i=0;i<numberVertices;i++)
{
vertexArray[i].marked = 0;
}
Like I said it seems to work for smaller data sets, but I do not understand why when I reinitialize it seems to seg fault.
Please let me know your thoughts and suggestions!
Valgrind Output On An Example Case:
==6634== Memcheck, a memory error detector
==6634== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==6634== Using Valgrind-3.6.0 and LibVEX; rerun with -h for copyright info
==6634== Command: ./a.out 100S.txt
==6634==
==6634== Conditional jump or move depends on uninitialised value(s)
==6634== at 0x400C13: checkonqueue (bfs.c:160)
==6634== by 0x400B7F: BFS (bfs.c:142)
==6634== by 0x40094A: main (bfs.c:103)
==6634==
==6634== Invalid write of size 4
==6634== at 0x40096E: main (bfs.c:107)
==6634== Address 0x4d00000041 is not stack'd, malloc'd or (recently) free'd
==6634==
==6634==
==6634== Process terminating with default action of signal 11 (SIGSEGV)
==6634== Access not within mapped region at address 0x4D00000041
==6634== at 0x40096E: main (bfs.c:107)
==6634== If you believe this happened as a result of a stack
==6634== overflow in your program's main thread (unlikely but
==6634== possible), you can try to increase the size of the
==6634== main thread stack using the --main-stacksize= flag.
==6634== The main thread stack size used in this run was 10485760.
==6634==
==6634== HEAP SUMMARY:
==6634== in use at exit: 3,448 bytes in 181 blocks
==6634== total heap usage: 181 allocs, 0 frees, 3,448 bytes allocated
==6634==
==6634== LEAK SUMMARY:
==6634== definitely lost: 0 bytes in 0 blocks
==6634== indirectly lost: 0 bytes in 0 blocks
==6634== possibly lost: 0 bytes in 0 blocks
==6634== still reachable: 3,448 bytes in 181 blocks
==6634== suppressed: 0 bytes in 0 blocks
==6634== Reachable blocks (those to which a pointer was found) are not shown.
==6634== To see them, rerun with: --leak-check=full --show-reachable=yes
==6634==
==6634== For counts of detected and suppressed errors, rerun with: -v
==6634== Use --track-origins=yes to see where uninitialised values come from
==6634== ERROR SUMMARY: 16120 errors from 2 contexts (suppressed: 6 from 6)
Segmentation fault (core dumped)
check on queue function:
int checkonqueue(int * q, int value)
{
int i = 0;
for(i=0;i < max;i++)
{
if(q[i] == value)
{
return 1;
}
}
return 0;
}
line 160 is the line of the if condition

C: Please help me debug this memory-related seg fault

I have the following C code:
static void* heap;
static unsigned int ptr;
int main(void) {
...
heap=(void*)malloc(10000*sizeof(char));
ptr=&heap;
/*Actual sniffing*/
pcap_loop(handle,-1,callback,NULL);
return 0;
}
And here is the callback function that gets called every once in a while:
void callback(u_char *useless,const struct pcap_pkthdr* header,const u_char* packet){
const u_char *payload;
...
payload = (u_char *)(packet + size_ethernet + size_ip + size_tcp);
unsigned int hash=DJBHash(payload,strlen(payload));
printf("%u\n",hash); //ok
int len=strlen(payload)*sizeof(u_char);
printf("len:%d, ptr:%d\n",len,ptr); //ok
memcpy(ptr,(char)payload,len*sizeof(u_char)); //I'm getting a seg fault here!
ptr+=len;
}
Here is my dump from valgrind:
==8687== Memcheck, a memory error detector
==8687== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==8687== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
==8687== Command: ./ByteCache
==8687==
==8687== Syscall param socketcall.setsockopt(optval) points to uninitialised byte(s)
==8687== at 0x514D12A: setsockopt (syscall-template.S:82)
==8687== by 0x4E34991: ??? (in /usr/lib/libpcap.so.1.1.1)
==8687== by 0x4E34AB2: ??? (in /usr/lib/libpcap.so.1.1.1)
==8687== by 0x401A3F: main (ByteCache.c:123)
==8687== Address 0x7fefffb42 is on thread 1's stack
==8687==
2912431451
len:12, ptr:6304012
==8687== Invalid read of size 8
==8687== at 0x4C2A337: memcpy (mc_replace_strmem.c:635)
==8687== by 0x4018CB: callback (ByteCache.c:77)
==8687== by 0x4E34E24: ??? (in /usr/lib/libpcap.so.1.1.1)
==8687== by 0x4E3A818: pcap_loop (in /usr/lib/libpcap.so.1.1.1)
==8687== by 0x401AB4: main (ByteCache.c:133)
==8687== Address 0x80 is not stack'd, malloc'd or (recently) free'd
==8687==
==8687==
==8687== Process terminating with default action of signal 11 (SIGSEGV)
==8687== Access not within mapped region at address 0x80
==8687== at 0x4C2A337: memcpy (mc_replace_strmem.c:635)
==8687== by 0x4018CB: callback (ByteCache.c:77)
==8687== by 0x4E34E24: ??? (in /usr/lib/libpcap.so.1.1.1)
==8687== by 0x4E3A818: pcap_loop (in /usr/lib/libpcap.so.1.1.1)
==8687== by 0x401AB4: main (ByteCache.c:133)
==8687== If you believe this happened as a result of a stack
==8687== overflow in your program's main thread (unlikely but
==8687== possible), you can try to increase the size of the
==8687== main thread stack using the --main-stacksize= flag.
==8687== The main thread stack size used in this run was 8388608.
==8687==
==8687== HEAP SUMMARY:
==8687== in use at exit: 22,711 bytes in 11 blocks
==8687== total heap usage: 41 allocs, 30 frees, 38,352 bytes allocated
==8687==
==8687== LEAK SUMMARY:
==8687== definitely lost: 0 bytes in 0 blocks
==8687== indirectly lost: 0 bytes in 0 blocks
==8687== possibly lost: 0 bytes in 0 blocks
==8687== still reachable: 22,711 bytes in 11 blocks
==8687== suppressed: 0 bytes in 0 blocks
==8687== Reachable blocks (those to which a pointer was found) are not shown.
==8687== To see them, rerun with: --leak-check=full --show-reachable=yes
==8687==
==8687== For counts of detected and suppressed errors, rerun with: -v
==8687== Use --track-origins=yes to see where uninitialised values come from
==8687== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 4 from 4)
Segmentation fault
Unfortunately, I can't seem to make much sense of it.
Any insight greatly appreciated.
Many thanks in advance,
Thanks to Kerrick SB, I've gotten one step further.
Here now is the output:
eamorr#Compaq6000:/mnt/eamorr/workspace/ByteCache/Debug# ./ByteCache
361457034
len:872, ptr:6304000
46267872
len:12, ptr:-92779411
Segmentation fault
I can see a negative ptr? I have no idea how this is possible. I've even changed ptr to type unsigned int.
I don't think you want to do ptr = &heap, you want ptr = heap. malloc returns a pointer to the memory it allocated, which seems to be what you're trying to refer to in your callback.
You only want to use the & to get the address of something. For example:
MyStructure MyVariable;
void* pAPointer = &MyVariable;
If you're malloc-ing you get a pointer returned so:
MyStructure *pPointerToStructure = malloc(sizeof(MyStructure));
to use the & on pPointerToStructure gives you the pointer to the pointer, not to the allocated memory from the malloc call
memcpy takes void pointers as its arguments, yet you're casting the second argument to a char. To fix this:
memcpy(ptr, (const void *) payload, len * sizeof(u_char));
For that matter, why don't you declare ptr as void** (i.e. say static void ** ptr;)?
Also, why all the excessive casting? You don't need to cast the result of malloc() or of the payload = assignment, as they're already the correct type. Finally, len should probably be of type size_t, because it's a size type (i.e. unsigned).

Resources