I recently started learning C and I'm currently working on a program that receives a text input from the user and prints the text so that each line will contain exactly 60 characters. In the exercise I was asked to implement 2 data structures for this program: a buffer, and a linked-list.
here is what I've come up with:
#include <stdio.h>
#include <stdlib.h>
#define SIZE 60
struct Node{
char data[SIZE + 1];
struct Node *next;
}; /* Node representation */
void readText(int , void *); /* function that reads the text */
void printText(int , void * , int); /* function that prints the text */
void addNode(struct Node**); /* function that adds a node to the previous node in the linked-list */
int main()
{
int choice;
printf("Hello! This program receives a text input and prints it so that each line will contain the
length of 60 characters\n");
printf("In order to start, please, enter the type of data structure that you wish to implement (0
for Buffer, 1 for Linked-List):\n");
scanf("%d", &choice);
if(choice == 0) /* buffer choice */
{
char *bufferPointer;
bufferPointer = (char *)calloc(SIZE + 1, sizeof(char));
readText(0 , &bufferPointer); /* calling the read-text function to implement buffer */
}
else if(choice == 1) /* Linked-list choice */
{
struct Node *nodePointer;
nodePointer = (struct Node*)calloc(SIZE + 1, sizeof(struct Node));
nodePointer->next = NULL;
readText(1 , &nodePointer); /* calling the read-text function to implement linked list */
}
else /* means the user entered wrong type */
{
printf("Error! you have entered an invalid value!\n");
}
return 0;
}
void readText(int choice , void *pointer)
{
int c;
int i;
i = 0;
if(choice == 0)
{
char *bufPointer;
bufPointer = (char *)pointer;
printf("Enter the text you want to write.\nEnd, by entering (CTRL + D) -> Linux , (CTRL + Z) -> Windows\n");
while((c = getchar()) != EOF)
{
if(i == SIZE)
{
bufPointer = (char *)realloc(bufPointer, (SIZE + 1) *sizeof(char));
i = 0;
}
if(bufPointer == NULL)
{
printf("Sorry! The memory allocation has failed!\n");
exit(0);
}
bufPointer[i] = c;
i++;
}
printText(0 , &bufPointer, i);
free(bufPointer);
}
if(choice == 1)
{
struct Node *nPointer;
nPointer = (struct Node*) pointer;
printf("Enter the text you want to write.\nEnd, by entering (CTRL + D) -> Linux , (CTRL + Z) -> Windows\n");
while((c = getchar()) != EOF)
{
if(i == SIZE)
{
addNode(&nPointer);
i = 0;
}
if(nPointer == NULL)
{
printf("Sorry! The memory allocation has failed!\n");
exit(0);
}
nPointer->data[i] = c;
i++;
}
printText(1 , &nPointer , i);
free(nPointer);
}
}
void addNode(struct Node** node)
{
struct Node *newNode;
newNode = calloc(SIZE + 1 , sizeof(struct Node));
if(newNode == NULL)
{
printf("Sorry! The memory allocation has failed!\n");
exit(0);
}
newNode->next = (*node);
(*node) = newNode;
}
void printText(int choice , void *pointer , int length)
{
int j;
if(choice == 0)
{
char *bufPointer;
bufPointer = (char *) pointer;
for(j = 0; j < length; j++)
{
if((j % SIZE == 0) && (j != 0))
{
printf("\n");
}
putchar(bufPointer[j]);
}
}
if(choice == 1)
{
struct Node *head;
head = (struct Node*) pointer;
while(head != NULL)
{
for(j = 0; j < length; j++)
{
putchar(head->data[j]);
}
if(length >= SIZE)
{
printf("\n");
}
head = head->next;
}
}
}
(sorry for the bad intendation!!)
When I compile it, it doesn't show any compilation error. However, whenever I run it, it gives me the following error:
user@ubuntu:~/Desktop/Maman12$ make
gcc -g -ansi -Wall -pedantic myText.c -o myText
user@ubuntu:~/Desktop/Maman12$ ./myText
Hello! This program receives a text input and prints it so that each line will contain the length of
60 characters
In order to start, please, enter the type of data structure that you wish to implement (0 for Buffer,
1 for Linked-List):
0
Enter the text you want to write.
End, by entering (CTRL + D) -> Linux , (CTRL + Z) -> Windows
asfasf
*** Error in `./myText': free(): invalid pointer: 0xbffebb58 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x67377)[0xb75d6377]
/lib/i386-linux-gnu/libc.so.6(+0x6d2f7)[0xb75dc2f7]
/lib/i386-linux-gnu/libc.so.6(+0x6dc31)[0xb75dcc31]
./myText[0x804875d]
./myText[0x8048632]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf7)[0xb7587637]
./myText[0x80484e1]
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:02 367783 /home/user/Desktop/Maman12/myText
08049000-0804a000 r--p 00000000 08:02 367783 /home/user/Desktop/Maman12/myText
0804a000-0804b000 rw-p 00001000 08:02 367783 /home/user/Desktop/Maman12/myText
09a32000-09a53000 rw-p 00000000 00:00 0 [heap]
b7400000-b7421000 rw-p 00000000 00:00 0
b7421000-b7500000 ---p 00000000 00:00 0
b753c000-b7558000 r-xp 00000000 08:02 931606 /lib/i386-linux-gnu/libgcc_s.so.1
b7558000-b7559000 rw-p 0001b000 08:02 931606 /lib/i386-linux-gnu/libgcc_s.so.1
b756f000-b771f000 r-xp 00000000 08:02 933356 /lib/i386-linux-gnu/libc-2.23.so
b771f000-b7721000 r--p 001af000 08:02 933356 /lib/i386-linux-gnu/libc-2.23.so
b7721000-b7722000 rw-p 001b1000 08:02 933356 /lib/i386-linux-gnu/libc-2.23.so
b7722000-b7725000 rw-p 00000000 00:00 0
b773a000-b773d000 rw-p 00000000 00:00 0
b773d000-b773f000 r--p 00000000 00:00 0 [vvar]
b773f000-b7740000 r-xp 00000000 00:00 0 [vdso]
b7740000-b7762000 r-xp 00000000 08:02 931813 /lib/i386-linux-gnu/ld-2.23.so
b7762000-b7763000 rw-p 00000000 00:00 0
b7763000-b7764000 r--p 00022000 08:02 931813 /lib/i386-linux-gnu/ld-2.23.so
b7764000-b7765000 rw-p 00023000 08:02 931813 /lib/i386-linux-gnu/ld-2.23.so
bffcd000-bffee000 rw-p 00000000 00:00 0 [stack]
X��Aborted (core dumped)
Is there a way to figure it out? I know that it is connected to the free function, but I don't understand what's wrong with..
Thank you in advance for your help!
It appears as though you are actually calling free
on the pointers themselves, rather than the memory they point to. This is occuring due to the fact that you are taking the addresses of the pointers with the address-of operator (&
) when you pass them to your functions, rather than passing the values that the pointers are storing. This will result in undefined behaviour, due to the fact that the pointers are likely stored on the stack and not intended to be free
d. This undefined behaviour is manifesting itself as the error message and subsequent abortion of your program. I suggest you directly pass the pointers and see if that makes a difference.
EDIT: I forgot to mention that were the pointer parameters of the functions char *
/struct Node *
rather than void *
, you would get a compiler warning stating that the pointer passed has a different indirection level than the function expects.