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)
Related
Context: Explanation of pointing to same address problem
compile:
gcc \
-Wpointer-arith -Wendif-labels \
-Wimplicit-fallthrough -Wmissing-format-attribute \
-Wcast-function-type -Wshadow=compatible-local \
-Wformat-security -Wno-format-truncation -Wno-stringop-truncation \
main.c &&./a.out dat/test.csv
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<errno.h>
enum {MAXB = 128, NELEM = 10};
typedef struct data_t{
char *name;
int id;
double balance;
}data_t;
int main(int argc,char **argv)
{
if(argc < 2){
printf("No file input.foramt a.out filename. %s\n",argv[1]);
exit(EXIT_FAILURE);
}
FILE *fp = fopen(argv[1],"r");
if(fp == NULL){
printf("file not found\n");
exit(EXIT_FAILURE);
}
char buffer[MAXB] = "";
const char *delim = ",\n";
int index = 0;
data_t **array = malloc(NELEM * sizeof *array);
if(!array){ /* validate EVERY allocation */
perror("malloc-array failed\n");
exit(EXIT_FAILURE);
}
/* protect the allocation bounds, you only have NELEM pointers */
while (index < NELEM && fgets(buffer,sizeof buffer,fp))
{
data_t customer;
size_t len = 0;
char *tmp; /* temporary pointer to use w/strtok() */
tmp = strtok(buffer,delim); /* token for name */
if(!tmp) /* validate token */
{
fputs("error: strtok() name.\n",stderr);
exit(EXIT_FAILURE);
}
len = strlen(tmp); /* get length */
customer.name = malloc(len+1); /* allocate for string */
if(!customer.name)
{
perror("malloc-customer.name\n");
exit(EXIT_FAILURE);
}
memcpy(customer.name,tmp, len +1); /* copy tmp to .name */
if(!(tmp = strtok(NULL,delim))) /* token & validations */
{
fprintf(stderr,"error: strtok() -id.\n");
exit(EXIT_FAILURE);
}
/* MINIMAL conversion validation with sscanf() */
if(sscanf(tmp,"%d",&customer.id) != 1){
fprintf(stderr,"error: invalid integer value for line[%d]\n",index+1);
continue;
/* exit(EXIT_FAILURE); */
}
if(!(tmp = strtok(NULL,delim))){
fprintf(stderr,"\nerror: strtok()-balance shuld have more line\n");
continue;
// exit(EXIT_FAILURE);
}
if(sscanf(tmp,"%lf", &customer.balance) != 1){
fprintf(stderr,"error: invalid float value for line[%d]\n", index+1);
/* exit(EXIT_FAILURE); */
continue;
}
array[index] = malloc(sizeof *array[index]); /* allocate struct */
if(!array[index]){ /* validate!! */
perror("malloc-array[index]");
exit(EXIT_FAILURE);
}
*array[index] = customer; /* assign struct */
index += 1;
}
fclose(fp);
int i;
printf("\nname\tid\t balance\n\n");
for(i = 0; i< index; i++)
printf("%s \t%d\t%f\n",array[i]->name,array[i]->id,array[i]->balance);
for(i = 0; i< index; i++)
{
if(array[i]->name)
free(array[i]->name); /* free allocated block for name */
if(array[i])
free(array[i]); /* free allocated array index */
}
free(array);
exit(EXIT_FAILURE);
}
cat dat/test.csv returns
name,id,balance
test1,11,1.2334
test2,12,1.133
test3,13,1.3334
test4,14,1.4334
command valgrind -s --leak-check=full ./a.out dat/test.csv output:
==494197== Memcheck, a memory error detector
==494197== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==494197== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==494197== Command: ./a.out dat/test.csv
==494197==
error: invalid integer value for line[1]
name id balance
test1 11 1.233400
test2 12 1.133000
test3 13 1.333400
test4 14 1.433400
==494197== Memcheck, a memory error detector
==494197== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==494197== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==494197== Command: ./a.out dat/test.csv
==494197==
error: invalid integer value for line[1]
name id balance
test1 11 1.233400
test2 12 1.133000
test3 13 1.333400
test4 14 1.433400
==494197==
==494197== HEAP SUMMARY:
==494197== in use at exit: 5 bytes in 1 blocks
==494197== total heap usage: 13 allocs, 12 frees, 5,797 bytes allocated
==494197==
==494197== 5 bytes in 1 blocks are definitely lost in loss record 1 of 1
==494197== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==494197== by 0x10951D: main (in /home/jian/helloc/a.out)
==494197==
==494197== LEAK SUMMARY:
==494197== definitely lost: 5 bytes in 1 blocks
==494197== indirectly lost: 0 bytes in 0 blocks
==494197== possibly lost: 0 bytes in 0 blocks
==494197== still reachable: 0 bytes in 0 blocks
==494197== suppressed: 0 bytes in 0 blocks
==494197==
==494197== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
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
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
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.
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.