How to free this strdup? - c

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.

Related

segmentation fault (c language)

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

POSIX semaphores - cannot determine what causes segmentation fault

I'm working on the sleeping barber problem (using FIFO queue and shared memory), and I have a problem. I try to run this program just to see what is shown, however, I get segmentation fault every time. In the code I check, if semaphores are created successfully, if shared memory is created properly, but the program crashing must come from different place, which I cannot seem to find. I also tried to use Valgrind but what I got is:
Valgrind for the newer version of code:
However, when I try to run the code I still get segfault
==187== Memcheck, a memory error detector
==187== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==187== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==187== Command: ./barber
==187==
Error while executing program, invalid amount of arguments==187==
==187== HEAP SUMMARY:
==187== in use at exit: 0 bytes in 0 blocks
==187== total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
==187==
==187== All heap blocks were freed -- no leaks are possible
==187==
==187== For lists of detected and suppressed errors, rerun with: -s
==187== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==124== Memcheck, a memory error detector
==124== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==124== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==124== Command: ./barber
==124==
==124== Invalid read of size 1
==124== at 0x1094DD: main (in /mnt/c/users/Czaro/ubuntu/lab6posix/barber)
==124== Address 0x2 is not stack'd, malloc'd or (recently) free'd
==124==
==124==
==124== Process terminating with default action of signal 11 (SIGSEGV)
==124== Access not within mapped region at address 0x2
==124== at 0x1094DD: main (in /mnt/c/users/Czaro/ubuntu/lab6posix/barber)
==124== If you believe this happened as a result of a stack
==124== overflow in your program's main thread (unlikely but
==124== possible), you can try to increase the size of the
==124== main thread stack using the --main-stacksize= flag.
==124== The main thread stack size used in this run was 8388608.
glut==124==
==124== HEAP SUMMARY:
==124== in use at exit: 125 bytes in 4 blocks
==124== total heap usage: 5 allocs, 1 frees, 1,149 bytes allocated
==124==
==124== LEAK SUMMARY:
==124== definitely lost: 0 bytes in 0 blocks
==124== indirectly lost: 0 bytes in 0 blocks
==124== possibly lost: 0 bytes in 0 blocks
==124== still reachable: 125 bytes in 4 blocks
==124== suppressed: 0 bytes in 0 blocks
==124== Reachable blocks (those to which a pointer was found) are not shown.
==124== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==124==
==124== For lists of detected and suppressed errors, rerun with: -s
==124== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault
I'd greatly appreciate every kind of help!
The code for barber (newer version, with changes given by #AndrewHenle looks like this:
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "functions.h"
#include <sys/mman.h>
#include <unistd.h>
int main(char* argv[], int argc)
{
if(argc < 2){
printf("Error while executing program, invalid amount of arguments");
return 0;
}
sem_t *barber;
sem_t *queue;
int seats;
int sharedmem, waitRoomSize;
struct Queue waitroom;
barber = sem_open("Barber", O_CREAT | O_RDWR, 0666, 1);
if((barber == SEM_FAILED)){
printf("Error while creating semaphore for barber");
exit(1);
}
queue = sem_open("Queue", O_CREAT | O_RDWR, 0666, 1);
if((queue == SEM_FAILED)) {
printf("Error while creating semaphore for queue");
exit(1);
}
seats = atoi(argv[1]);
void *space;
queueinit(waitroom, seats);
sharedmem = shm_open("Queue", O_RDWR, 0666);
if(sharedmem==-1){
printf("Error while getting shared memory");
exit(1);
}
waitRoomSize = ftruncate(sharedmem, sizeof(waitroom));
if((waitRoomSize ==-1)){
printf("Error while getting size");
exit(1);
}
space = mmap(NULL, sizeof(struct Queue), PROT_READ | PROT_WRITE, MAP_SHARED, sharedmem, 0);
if((space == MAP_FAILED)){
printf("B³¹d podczas mapowania pamiêci");
exit(1);
}
while(1)
{
printf("Starting work...");
sem_wait(queue);
sem_post(queue);
if(isEmpty(waitroom)) {
sem_wait(barber);
printf("Falling asleep \n");
sem_post(barber);
printf("Waking up \n");
}
sem_wait(queue);
sem_post(queue);
int id = get(waitroom);
printf("Customer: %d, please sit on the chair", id);
printf("I start making haircut: %d", id);
sleep(2);
printf("Finished making haircut for: %d", id);
}
sem_close(barber);
sem_unlink("Barber");
sem_close(queue);
sem_unlink("Queue");
}
Previous version:
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "functions.h"
#include <sys/mman.h>
#include <unistd.h>
int main(char* argv, int argc)
{
sem_t *barber;
sem_t *queue;
int seats;
int sharedmem, waitRoomSize;
struct Queue waitroom;
barber = sem_open("Barber", O_CREAT | O_RDWR, 0666, 1);
if((barber == SEM_FAILED)){
printf("Error while creating semaphore for barber");
exit(1);
}
queue = sem_open("Queue", O_CREAT | O_RDWR, 0666, 1);
if((queue == SEM_FAILED)) {
printf("Error while creating semaphore for queue");
exit(1);
}
seats = atoi(argv[1]);
void *space;
queueinit(waitroom, seats);
if((sharedmem = shm_open("Queue", O_RDWR, 0666)==-1)){
printf("Error while getting shared memory");
exit(1);
}
if((waitRoomSize = ftruncate(sharedmem, sizeof(waitroom))==-1)){
printf("Error while getting size");
exit(1);
}
if((space = mmap(NULL, sizeof(struct Queue), PROT_READ | PROT_WRITE, MAP_SHARED, sharedmem, 0) == MAP_FAILED)){
printf("Błąd podczas mapowania pamięci");
exit(1);
}
while(1)
{
printf("Starting work...");
sem_wait(queue);
sem_post(queue);
if(isEmpty(waitroom)) {
sem_wait(barber);
printf("Falling asleep \n");
sem_post(barber);
printf("Waking up \n");
}
sem_wait(queue);
sem_post(queue);
int id = get(waitroom);
printf("Customer: %d, please sit on the chair", id);
printf("I start making haircut: %d", id);
sleep(2);
printf("Finished making haircut for: %d", id);
}
sem_close(barber);
sem_unlink("Barber");
sem_close(queue);
sem_unlink("Queue");
}
The FIFO queue is implemented like this:
#ifndef FUNCTIONS_H_INCLUDED
#define FUNCTIONS_H_INCLUDED
#include <stdlib.h>
#include <unistd.h>
struct Queue{
int* elems;
int qsize;
int head;
int tail;
int capacity;
};
void queueinit(struct Queue q, int capacity)
{
q.elems = malloc(capacity*(sizeof(int)));
q.capacity = capacity;
q.head = 0;
q.qsize = 0;
q.tail = capacity-1;
}
int isFull(struct Queue q)
{
return (q.qsize == q.capacity);
}
int isEmpty(struct Queue q)
{
return (q.qsize == 0);
}
void push(struct Queue q, int val)
{
if(isFull(q)){
printf("Kolejka pe³na");
return;
}
q.tail = (q.tail +1) % q.capacity;
q.elems[q.tail] = val;
q.qsize = q.qsize +1;
printf("%d zajmuje miejsce w kolejce", val);
}
int get(struct Queue q)
{
if(isEmpty(q))
{
printf("kolejka pusta");
return -1;
}
int val = q.elems[q.head];
q.head = (q.head +1) % q.capacity;
q.qsize = q.qsize -1;
printf("%d opuszcza zak³ad", val);
}
#endif // FUNCTIONS_H_INCLUDED

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