segmentation fault (c language) - c

While trying to recover jpgs from a raw file in week4 of CS50 course , I got this seg fault error which I can't understand why or how it is caused, all I can tell is that according to valgrind line 110 causes this issue
I am fairly new to c language
int main(int argc, char *argv[])
{
// check if one command arg is passed
if (argc > 2 )
{
printf("Usage: ./recover image\n");
return 1;
}
// try to open file to read from
FILE *file = fopen(argv[1], "r");
if (!file)
{
return 1;
}
BYTE bytes[512];
int x =0 ;
char num[10];
FILE* output =NULL;
while (fread(&bytes, 512, 1, file) == 1)
{
// first step create file name
sprintf(num, "%03i.jpg",x);
// check for start of jpg file
if (bytes[0]==0xff && bytes[1] ==0xd8 && bytes[2]== 0xff && (bytes[3] & 0xf0) == 0xe0 )
{
printf("Found file {%i}", x);
output = fopen(num , "w");
fwrite(&bytes ,512 ,1 ,output);
x++;
}
else
{
fwrite(&bytes , 512 , 1 , output);
}
}
return 0;
}
output of valgrind
==12934== Invalid read of size 4
==12934== at 0x4A1C521: fwrite (iofwrite.c:37)
==12934== by 0x4014CA: main (recover.c:110)
==12934== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==12934==
==12934==
==12934== Process terminating with default action of signal 11 (SIGSEGV)
==12934== Access not within mapped region at address 0x0
==12934== at 0x4A1C521: fwrite (iofwrite.c:37)
==12934== by 0x4014CA: main (recover.c:110)
==12934== If you believe this happened as a result of a stack
==12934== overflow in your program's main thread (unlikely but
==12934== possible), you can try to increase the size of the
==12934== main thread stack using the --main-stacksize= flag.
==12934== The main thread stack size used in this run was 8388608.
==12934==
==12934== HEAP SUMMARY:
==12934== in use at exit: 472 bytes in 1 blocks
==12934== total heap usage: 2 allocs, 1 frees, 4,568 bytes allocated
==12934==
==12934== LEAK SUMMARY:
==12934== definitely lost: 0 bytes in 0 blocks
==12934== indirectly lost: 0 bytes in 0 blocks
==12934== possibly lost: 0 bytes in 0 blocks
==12934== still reachable: 472 bytes in 1 blocks
==12934== suppressed: 0 bytes in 0 blocks
==12934== Rerun with --leak-check=full to see details of leaked memory
==12934==
==12934== For lists of detected and suppressed errors, rerun with: -s
==12934== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
zsh: segmentation fault valgrind ./recover card.raw

take this one
int main(int argc, char *argv[])
{
// check if one command arg is passed
if (argc > 2 )
{
printf("Usage: ./recover image\n");
return 1;
}
// try to open file to read from
FILE *file = fopen(argv[1], "r");
if (!file)
{
return 1;
}
BYTE bytes[512];
int x =0 ;
char num[10];
FILE* output =NULL;
while (fread(bytes, 512, 1, file) == 1)
{
// check for file start
if (bytes[0]==0xff && bytes[1] ==0xd8 && bytes[2]== 0xff && (bytes[3] & 0xf0) == 0xe0 )
{
if (output)
{
fclose(output);
}
// create file name
sprintf(num, "%03i.jpg",x);
printf("Found file {%i}\n", x);
output = fopen(num , "w");
fwrite(&bytes ,512 ,1 ,output);
x++;
}
else if (output)
{
fwrite(bytes , 512 , 1 , output);
}
}
if(output)
{
fclose(output);
}
return 0;
}
notice the use of fclose(output); to close file descriptors, as noted by Marek R

changing
else
{
fwrite(&bytes , 512 , 1 , output);
}
to
else if (output)
{
fwrite(&bytes , 512 , 1 , output);
}
generates the pictures
thanks to Marek R for mentioning the if file is opened comment

Related

Invalid read using valgrind

After a compilation with no warnings and errors for my file reorg.c, I am running the program using Valgrind and I am getting the following output. I am trying to understand why I am getting a segmentation fault but I can't really find something wrong with line 35:
Memcheck, a memory error detector
==29338== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==29338== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==29338== Command: ./reorg /opt/lsde/dataset-sf100/
==29338==
==29338== Invalid read of size 2
==29338== at 0x109398: main (reorg.c:35)
==29338== Address 0x12cb4008 is not stack'd, malloc'd or (recently) free'd
==29338==
==29338==
==29338== Process terminating with default action of signal 11 (SIGSEGV)
==29338== Access not within mapped region at address 0x12CB4008
==29338== at 0x109398: main (reorg.c:35)
==29338== If you believe this happened as a result of a stack
==29338== overflow in your program's main thread (unlikely but
==29338== possible), you can try to increase the size of the
==29338== main thread stack using the --main-stacksize= flag.
==29338== The main thread stack size used in this run was 8388608.
==29338==
==29338== HEAP SUMMARY:
==29338== in use at exit: 15,280 bytes in 10 blocks
==29338== total heap usage: 10 allocs, 0 frees, 15,280 bytes allocated
==29338==
==29338== LEAK SUMMARY:
==29338== definitely lost: 5,120 bytes in 5 blocks
==29338== indirectly lost: 0 bytes in 0 blocks
==29338== possibly lost: 0 bytes in 0 blocks
==29338== still reachable: 10,160 bytes in 5 blocks
==29338== suppressed: 0 bytes in 0 blocks
==29338== Rerun with --leak-check=full to see details of leaked memory
==29338==
==29338== For lists of detected and suppressed errors, rerun with: -s
==29338== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)
This is the code of the reorg.c program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "utils.h"
Person *person_map;
unsigned int *knows_map;
unsigned short *interest_map;
unsigned long person_num = 0;
int main(int argc, char *argv[]) {
unsigned long file_length;
interest_map = (unsigned short *) mmapr(makepath(argv[1], "interest", "bin"), &file_length);
printf("amin1");
knows_map = (unsigned int *) mmapr(makepath(argv[1], "knows", "bin"), &file_length);
printf("amin2");
person_map = (Person *) mmapr(makepath(argv[1], "person", "bin"), &file_length);
printf("amin3");
knows_map = (unsigned int *) mmapr(makepath(argv[1], "knows", "bin"), &file_length);
printf("knows");
person_map = (Person *) mmapr(makepath(argv[1], "person", "bin"), &file_length);
printf("person");
person_num = file_length/sizeof(person_map);
int counter=0;
FILE* fp_knows2 = fopen(makepath(argv[1], "knows2", "bin"), (char*) "w");
FILE* fp_person2 = fopen(makepath(argv[1], "person2", "bin"), (char*) "w");
long knows2_bytesize;
int *knows2_map;
int *person2_map;
long person2_bytesize;
for(long i=0; i<person_num; i++) {
for(long j = 0; j < person_map[i].knows_n; j++) {
int friend = knows_map[person_map[i].knows_first+j]; // person in my knows-list
if (person_map[friend].location == person_map[i].location) {
counter++;
fwrite(&friend, 1,sizeof(int), fp_knows2);
}
}
if(counter > 0){
fwrite(&person_map[i], 1, sizeof(int), fp_person2);
}
counter=0;
}
fclose(fp_knows2);
fclose(fp_person2);
person2_map = (int*) mmapr(makepath(argv[1], "person2","bin"), &person2_bytesize);
knows2_map = (int*) mmapr(makepath(argv[1], "knows2","bin"), &knows2_bytesize);
return 0;
}
And this is the code of the utils.h program that am including in:
#define REPORTING_N 1000000
#define LINEBUFLEN 1024
typedef unsigned long byteoffset;
typedef unsigned int entrycount;
typedef struct {
unsigned long person_id;
unsigned short birthday;
unsigned short location;
unsigned long knows_first;
unsigned short knows_n;
unsigned long interests_first;
unsigned short interest_n;
} Person;
void parse_csv(char* fname, void (*line_handler)(unsigned char nfields, char** fieldvals)) {
long nlines = 0;
FILE* stream = fopen(fname, "r");
if (stream == NULL) {
fprintf(stderr, "Can't read file at %s\n", fname);
exit(-1);
}
char line[LINEBUFLEN];
char* tokens[10];
unsigned int col, idx;
tokens[0] = line;
while (fgets(line, LINEBUFLEN, stream)) {
col = 0;
// parse the csv line into array of strings
for (idx=0; idx<LINEBUFLEN; idx++) {
if (line[idx] == '|' || line[idx] == '\n') {
line[idx] = '\0';
col++;
tokens[col] = &line[idx+1];
} // lookahead to find end of line
if (line[idx+1] == '\0') {
break;
}
}
(*line_handler)(col, tokens);
nlines++;
if (nlines % REPORTING_N == 0) {
printf("%s: read %lu lines\n", fname, nlines);
}
}
fclose(stream);
}
FILE* open_binout(char* filename) {
FILE* outfile;
outfile = fopen(filename, "wb");
if (outfile == NULL) {
fprintf(stderr, "Could not open %s for writing\n", filename);
exit(-1);
}
return outfile;
}
unsigned short birthday_to_short(char* date) {
unsigned short bdaysht;
char dmbuf[3];
dmbuf[2] = '\0';
dmbuf[0] = *(date + 5);
dmbuf[1] = *(date + 6);
bdaysht = atoi(dmbuf) * 100;
dmbuf[0] = *(date + 8);
dmbuf[1] = *(date + 9);
bdaysht += atoi(dmbuf);
return bdaysht;
}
void* mmapr(char* filename, byteoffset *filelen) {
int fd;
struct stat sbuf;
void *mapaddr;
if ((fd = open(filename, O_RDONLY)) == -1) {
fprintf(stderr, "failed to open %s\n", filename);
exit(1);
}
if (stat(filename, &sbuf) == -1) {
fprintf(stderr, "failed to stat %s\n", filename);
exit(1);
}
mapaddr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
if (mapaddr == MAP_FAILED) {
fprintf(stderr, "failed to mmap %s\n", filename);
exit(1);
}
*filelen = sbuf.st_size;
return mapaddr;
}
char* makepath(char* dir, const char* file, const char* ext) {
char* out = (char*) malloc(1024), *sep = (char*) "";
if (strlen(dir) && dir[strlen(dir)-1] != '/') sep = (char*) "/";
sprintf(out, "%s%s%s.%s", dir, sep, file, ext);
return out;
}

How to free this strdup?

I am using strdup to duplicated the value inside command. I also free it at the end of my loop to make sure I don't have anything leaking but valgrind seems to disagree with me and says that what is allocated with this strdup is leaking. Any ideas?
Here is my code:
int main(void)
{
init_ui();
hist_init(100);
char *command;
while (true) {
signal(SIGINT, SIG_IGN);
command = read_command();
if (command == NULL) {
break;
}
char *copy = strdup(command);
char *args[4096];
int tokens = 0;
char *next_tok = command;
char *curr_tok;
while((curr_tok = next_token(&next_tok, " \t\n\r")) != NULL) {
if(strncmp(curr_tok, "#", 1) == 0){
break;
}
args[tokens++] = curr_tok;
}
args[tokens] = NULL;
if(args[0] == NULL) {
continue;
}
hist_add(copy);
int builtin_status = handle_builtins(tokens, args);
if(builtin_status == 0) {
continue;
}
pid_t child = fork();
if(child == -1){
perror("fork");
}
else if(child == 0){
int ret = execvp(args[0], args);
if(ret == -1) {
perror("execvp");
}
close(fileno(stdin));
close(fileno(stdout));
close(fileno(stderr));
exit(EXIT_FAILURE);
}
else {
int status;
waitpid(child, &status, 0);
set_last_status(status);
}
hist_destroy();
free(copy);
}
return 0;
}
Here is what valgrind gives me, I really am trying to understand what is wrong because it seems like what is defined with this strdup is freed:
HEAP SUMMARY:
==359074== in use at exit: 18 bytes in 2 blocks
==359074== total heap usage: 72 allocs, 70 frees, 20,000 bytes allocated
==359074==
==359074== 18 bytes in 2 blocks are definitely lost in loss record 1 of 1
==359074== at 0x483977F: malloc (vg_replace_malloc.c:307)
==359074== by 0x4A7D23E: strdup (in /usr/lib/libc-2.31.so)
==359074== by 0x10A703: main (shell.c:85)
==359074==
==359074== LEAK SUMMARY:
==359074== definitely lost: 18 bytes in 2 blocks
==359074== indirectly lost: 0 bytes in 0 blocks
==359074== possibly lost: 0 bytes in 0 blocks
==359074== still reachable: 0 bytes in 0 blocks
==359074== suppressed: 0 bytes in 0 blocks
strdup() uses malloc() to allocate memory, so in order to reuse strdup(), copy must be freed.
As UnholySheep commented above, continues causing to ignore the free() statement. One solution to fix this issue is to put an extra free() statement before each continue.

munmap() not working when called from function

Im writing a library of functions that works with shared memory. The function I am writing to close the shared memory gives me a segfault whenever it gets to the munmap() part, but if i dont use the function and just let the code munmap() and shm_unlink at the end, it works. im very confused as to why. the code is below.
void close_table(table_t *tbl, char* name){
size_t size = sizeof(tbl->table_size);
printf("table_size: %d\n", tbl->table_size);
/* when the first part of if else statement runs its fine */
if(tbl->numP > 1){
printf("first if statement\n");
tbl->numP -= 1;
munmap(tbl, tbl->table_size);
}
/* when second part runs gives seg fault */
else{
tbl->numP -= 1;
munmap(tbl, tbl->table_size);
//close(tbl->shm_fd);
shm_unlink(tbl->name);
}
// Code omission
}
This is the open table function
table_t *open_table(char *name, int record_size, int max_records){
int shm_fd;
int table_size;
void* ptr;
table_t* tbl;
table_t controlBlock;
db_info info;
data_block data;
table_size = max_records * sizeof(controlBlock) * sizeof(info) *
sizeof(data);
if((shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666)) == -1){
exit(EXIT_FAILURE);
}
ftruncate(shm_fd, table_size);
ptr = mmap(NULL, table_size, PROT_WRITE | PROT_READ, MAP_SHARED, shm_fd,
0);
tbl = ptr;
tbl->shm_fd = shm_fd;
tbl->table_size = table_size;
tbl->max_records = max_records;
tbl->record_size = record_size;
if(tbl->numP >= 1){
tbl->numP += 1;
}
else{
tbl->numP = 1;
}
return tbl;
}
these are my structs
typedef struct{
int dbInfoId;
int deleted;
}db_info;
typedef struct{
int shm_fd;
int numP;
int control_id;
char *name;
int table_size;
int record_size;
int max_records;
db_info* dbInfo;
void* db;
}table_t;
typedef struct{
int id;
void* record;
}data_block;
valgrind says its an "invalid read of size 8
enter a command (just the number):
1. Add
2. Delete
3. Process
4. Close
5. # of processes
6. exit
4
table_size: 29360128
==6679== Invalid read of size 8
==6679== at 0x108C42: close_table (in /home/abiodun/Documents/Comp 3713/Assignment3_makeup/main)
==6679== by 0x108F15: main (main.c:40)
==6679== Address 0x5654010 is not stack'd, malloc'd or (recently) free'd
==6679==
==6679==
==6679== Process terminating with default action of signal 11 (SIGSEGV)
==6679== Access not within mapped region at address 0x5654010
==6679== at 0x108C42: close_table (in /home/abiodun/Documents/Comp 3713/Assignment3_makeup/main)
==6679== by 0x108F15: main (main.c:40)
==6679== If you believe this happened as a result of a stack
==6679== overflow in your program's main thread (unlikely but
==6679== possible), you can try to increase the size of the
==6679== main thread stack using the --main-stacksize= flag.
==6679== The main thread stack size used in this run was 8388608.
--6679-- REDIR: 0x50db950 (libc.so.6:free) redirected to 0x4c30cd0 (free)
==6679==
==6679== HEAP SUMMARY:
==6679== in use at exit: 0 bytes in 0 blocks
==6679== total heap usage: 2 allocs, 2 frees, 2,048 bytes allocated
==6679==
==6679== All heap blocks were freed -- no leaks are possible
==6679==
==6679== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
==6679==
==6679== 1 errors in context 1 of 1:
==6679== Invalid read of size 8
==6679== at 0x108C42: close_table (in /home/abiodun/Documents/Comp 3713/Assignment3_makeup/main)
==6679== by 0x108F15: main (main.c:40)
==6679== Address 0x5654010 is not stack'd, malloc'd or (recently) free'd
==6679==
==6679== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)
I figured it the answer. It turns out I was still trying to access variables in the tbl struct after it was unmapped. so to fix this I just created variabbles in the function and saved what I needed from the tbl struct before unmapping.
void close_table(table_t *tbl){
int size = tbl->table_size;
char* name = tbl->name;
int fd = tbl->shm_fd;
printf("table_size: %d\n", tbl->table_size);
if(tbl->numP > 1){
tbl->numP -= 1;
munmap(tbl, tbl->table_size);
close(fd);
}
else if(tbl->numP == 1){
tbl->numP -= 1;
munmap(tbl, size);
printf("unmap works\n"); fflush(stdout);
shm_unlink(name);
close(fd);
}

Correctly free alsa mixer resources

I'm writing some simple Alsa init code to setup a mixer, which I'll be using to set volume, etc. However, even basic code has memory leaks, despite using suggesting memory freeing method like snd_config_update_free_global(). If someone could check the snippet out and let me know what I'm missing, it would be greatly appreciated. Thanks!
#include <alsa/asoundlib.h>
#include <stdio.h>
#include <stdlib.h>
void PrintAlsaError(const char * str, int error_code) {
fprintf(stderr, str, snd_strerror(error_code));
}
int main() {
snd_mixer_t * handle;
snd_mixer_selem_id_t * sid;
snd_mixer_elem_t * elem;
const char * card = "default";
int error_code;
if ((error_code = snd_mixer_open(&handle, 0)) < 0) {
PrintAlsaError("unable to open handle, error: %s\n", error_code);
return -1;
} else if ((error_code = snd_mixer_attach(handle, card)) < 0) {
PrintAlsaError("unable to attach to card, error: %s\n", error_code);
snd_mixer_close(handle);
return -1;
} else if ((error_code = snd_mixer_selem_register(handle, NULL, NULL)) < 0) {
PrintAlsaError("unable to register handle, error: %s\n", error_code);
snd_mixer_close(handle);
return -1;
} else if ((error_code = snd_mixer_load(handle)) < 0) {
PrintAlsaError("unable to load handle, error: %s\n", error_code);
snd_mixer_close(handle);
return -1;
}
snd_mixer_selem_id_alloca(&sid);
if (!sid) {
fprintf(stderr, "couldn't get selem id\n");
}
if (!(elem = snd_mixer_first_elem(handle))) {
fprintf(stderr, "no elements in mixer\n");
}
snd_mixer_selem_get_id(elem, sid);
snd_mixer_close(handle);
snd_config_update_free_global();
return 0;
}
Here's the valgrind output:
==8389== HEAP SUMMARY:
==8389== in use at exit: 69,442 bytes in 193 blocks
==8389== total heap usage: 6,912 allocs, 6,719 frees, 591,848 bytes allocated
==8389==
==8389== LEAK SUMMARY:
==8389== definitely lost: 0 bytes in 0 blocks
==8389== indirectly lost: 0 bytes in 0 blocks
==8389== possibly lost: 0 bytes in 0 blocks
==8389== still reachable: 69,442 bytes in 193 blocks
==8389== suppressed: 0 bytes in 0 blocks
==8389== Rerun with --leak-check=full to see details of leaked memory
==8389==
==8389== For counts of detected and suppressed errors, rerun with: -v
==8389== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Why do I get a still reachable block after mallocing a char*?

I have the following code:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
void print_usage()
{
printf("%s\n", "usage");
}
int file_exist (char *filename)
{
struct stat buffer;
return (stat (filename, &buffer) == 0);
}
int parse_parameters(int argc, char *argv[], char** in)
{
unsigned int i1 = 1; // 0 is the filename
for (; i1 < argc; ++i1)
{
if( 0 == strcmp("-h", argv[i1]) )
{
print_usage();
return 0;
}
else if( 0 == strcmp("-i", argv[i1]) )
{
*in = malloc( sizeof(char) * strlen(argv[++i1]) + 1 );
strcpy(*in, argv[i1]);
continue;
}
else
{
print_usage();
return 1;
}
}
return 0;
}
int main(int argc, char *argv[])
{
if( argc != 3 )
{
print_usage();
return 0;
}
char* in = NULL;
int parse = parse_parameters(argc, argv, &in);
if ( 0 != parse )
return parse;
printf("in: %s\n", in);
FILE* finput = NULL ;
if (file_exist(in))
finput = fopen(in, "r");
if (finput == NULL) {
perror("fopen");
exit(1);
}
free(in);
fclose(finput);
return 0;
}
After running it with valgrind with following parameters:
./main -i input
I get the following:
==30977== Memcheck, a memory error detector
==30977== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==30977== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==30977== Command: ./main -i input
==30977==
in: input
fopen: No such file or directory
==30977==
==30977== HEAP SUMMARY:
==30977== in use at exit: 6 bytes in 1 blocks
==30977== total heap usage: 2 allocs, 1 frees, 574 bytes allocated
==30977==
==30977== 6 bytes in 1 blocks are still reachable in loss record 1 of 1
==30977== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30977== by 0x400946: parse_parameters (main.c:31)
==30977== by 0x4009E7: main (main.c:54)
==30977==
==30977== LEAK SUMMARY:
==30977== definitely lost: 0 bytes in 0 blocks
==30977== indirectly lost: 0 bytes in 0 blocks
==30977== possibly lost: 0 bytes in 0 blocks
==30977== still reachable: 6 bytes in 1 blocks
==30977== suppressed: 0 bytes in 0 blocks
==30977==
==30977== For counts of detected and suppressed errors, rerun with: -v
==30977== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Why is that ? If I try to pass in as char* then it won't get changed after the parse_parameters function.
Your program is exiting as a result of the exit (1) call, which occurs before you free (in). As a result you are seeing the valgrind message.

Resources