I've encounter an issue in Visual Studio which drives me crazy.
It is regarding unallocated pointers.
I wanted to write a simple linked list app.The problem is that freed and unallocated pointers are not NULL which prevents me from iterating the list.
Consider following C code
#include "stdafx.h"
#include <malloc.h>
typedef struct _item
{
char data;
struct _item * pNext;
}item, *pItem;
int _tmain(int argc, _TCHAR* argv[])
{
pItem listHead;
pItem listTemp;
pItem listCurr;
listHead = (pItem) malloc(sizeof(listHead));
listHead->data = '0';
listHead->pNext = NULL; //will create exception in free
listTemp = listHead;
while(listTemp->pNext != NULL) //issue 1
{
listTemp = listTemp->pNext;//0xfdfdfdfd - never NULL? how to check?
}
listCurr = (pItem) malloc(sizeof(listHead));
listCurr->data = '1';
listCurr->pNext = NULL; //will create exception in free
listTemp->pNext = listCurr;
listTemp = listHead;
while(listTemp->pNext != NULL) //issue 2
{
printf("%d ", listTemp->data - 48); //"0 "
listTemp = listTemp->pNext;
}
printf("%d ", listTemp->data - 48);
free(listTemp); //is set to oxfeeefee not to NULL? //issue 3
listTemp = listHead;
while(listTemp->pNext != NULL) //issue 4
{
listTemp = listTemp->pNext;
}
free(listTemp);//Not null?
return 0;
}
in line issue 1 and issue 2, listTemp->pNext is not NULL but 0xfdfdfdfd. This prevents from getting the last element in the list
in line issue 3, free doesn't set the freed pointer to null but to 0xfeeefeee. This prevents me from getting last element again.
How can i handle these issues?
Thanks for help.
You seem to have a few issues here. One problem you are having is that you are not allocating enough memory.
listHead = (pItem) malloc(sizeof(listHead));
listHead is a pointer. So you only allocate enough memory to hold a pointer, and not to hold your entire item struct. It should be:
listHead = (pItem) malloc(sizeof(item));
I can't see how issue 1 could ever not be NULL the first time through. Did you step through with a debugger? However, the problem with not allocating enough memory could definitely cause the problem with free(), and it's a little difficult to say for sure what other problems it might cause.
Syntax altered slightly to suit my compiler. The two main issues were (1) not allocating enough memory, as already commented. (2) wrong sequence for parsing the list.
#include <stdio.h>
#include <stdlib.h>
typedef struct item {
char data;
struct item * pNext;
} item, *pItem;
void show (pItem list, int cue) {
printf("List %d: ", cue);
while(list != NULL) {
printf("%c ", list->data);
list = list->pNext;
}
printf("\n");
}
int main(int argc, char* argv[]) {
pItem listHead, listTemp, listCurr;
listHead = malloc(sizeof(item));
listHead->data = '0';
listHead->pNext = NULL;
show(listHead, 1);
listCurr = malloc(sizeof(item));
listCurr->data = '1';
listCurr->pNext = NULL;
listHead->pNext = listCurr;
show(listHead, 2);
printf("Freeing: ");
while(listHead != NULL) {
listTemp = listHead;
printf("%c ", listHead->data);
listHead = listHead->pNext;
free(listTemp);
}
printf("\n");
show(listHead, 3);
return 0;
}
The above code follows your method of adding the next item to the tail of the list, but I would normally add it before the head and set a new listHead.
listCurr = malloc(sizeof(item));
listCurr->data = '1';
listCurr->pNext = listHead;
listHead = listCurr;
and this will also work for the first item provided you initialised listHead = NULL to indicate an empty list.
The answer is that you have to set the pointer to the freed memory to NULL yourself. The free function will only release the memory at the pointer back to the heap. The pointer parameter is passed by value and cannot be modified by the free function itself.
Also, you will need to retain a reference to the previous item in your list, so that when you do free the memory and set the pointer to NULL, you do it in the list items and not on the temporary pointer.
listCurr = NULL;
listTemp = listHead;
while(listTemp->pNext != NULL)
{
listCurr = listTemp;
listTemp = listTemp->pNext;
}
if(NULL != listCurr)
{
free(listCurr->pNext);
listCurr->pNext = NULL;
}
Related
I am required to have a list of structs of sentence nodes that point to a struct of word nodes. I am trying to print the user's input.
I have a program that runs properly when I manually give it the input (see test section of the code). It does not, however, work when I use my input1() function.
I've tried debugging it, but I can't seem to find the problem.
I removed all printf lines that I used to debug. I also removed all the irrelevant code.
I am looking to know how to fix it and what is wrong so I can run it with no problems.
What I learned from debugging it is that (only when using input1() and not in the test) the head is overwritten every time and all the nodes as well.
I also tried using a double pointer instead of returning para but that didn't help.
any help will be appreciated,
thanks in advance
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
typedef struct word
{
char * ch;//poiter to char
}
W;
typedef struct sentence
{
W * currentWord;//pointer to a word
int lineNumber;// holds the line number
int numbersOfWords;//holds the number of words
struct sentence* link;
}
sent;
typedef struct list
{
sent* head;
int count;
}
LISTS;
LISTS* createList()
{
LISTS* list;
list= (LISTS*) malloc (sizeof (LISTS));
if (list)
{
list-> head = NULL;
list-> count = 0;
}
return list;
} // createList
void printList(LISTS* list)
{
sent *temp = list -> head;
//iterate the entire linked list and print the data
while(temp != NULL)
{
printf("%s\n", temp->currentWord->ch);
temp = temp->link;
}
// printf("NULL\n");
}
void insertSentList (LISTS* list, W* itemPtr)
{
sent* newPtr; //new node
if (!(newPtr = (sent * ) malloc(sizeof(sent)))){
printf(" Memory can not be allocated.");
return;
}
newPtr->currentWord = itemPtr;
newPtr->link = NULL;
if(list->head == NULL)
{
list->head = newPtr;
}else{
sent* current = list->head;
while(current->link != NULL){
current = current->link;
}
current -> link = newPtr;
}
(list->count)++;
return;
} // insertList
LISTS * input1(LISTS *para)
{
char * line;
line = (char * ) malloc(1000 * sizeof(char));
line[0] = '\0';
while (line[0] != '\n')
{
W word;
word.ch = (char * ) malloc(100);
printf(" Please input a line : ");
fgets(line, 1000, stdin);
if(line[0] != '\n'){
strcpy(word.ch, line);
insertSentList(para,&word);
}
}
free(line);
return para;
}
int main()
{
///////////////////test////////////////
LISTS* list = createList();
W word;
word.ch= "word0 ";
W word1;
word1.ch= "word1 ";
W word2;
word2.ch= "word2";
insertSentList(list,&word);
insertSentList(list,&word1);
insertSentList(list,&word2);
insertSentList(list,&word);
insertSentList(list,&word1);
insertSentList(list,&word2);
printList(list);
///////////////////test////////////////
LISTS *para = createList();
para= input1(para);
printList(para);
return 0;
}
Main problem with the posted code is that "ownership" of the sent and W objects in a list is not well defined. For example word.ch= "word0 "; in main sets the ch pointer pointing to a string literal (which it does not own), but word.ch = malloc(100); in input1 points it to dynamically allocated memory (which it should own, and remember to free later). Because of this, memory allocations cannot be tracked reliably and, even in the cases where things appear to "work", there are multiple memory leaks. It also breaks when the inserted objects are local variables that do not live for the entire lifetime of the list object.
The simplest (if not necessarily the best or most efficient) solution would be to dynamically allocate all objects that go into the list, make the list own them all, and add a function to cleanup once done. To that end insertSentList could be modified as follows.
void insertSentList (LISTS* list, W* itemPtr)
{
sent* newPtr; //new node
if (!(newPtr = malloc(sizeof(sent)))){
printf(" Memory can not be allocated.\n");
return;
}
W *newItem = malloc(sizeof(W)); // <-- make a deep copy of the `itemPtr` argument
newItem->ch = strdup(itemPtr->ch); // including a copy of the string itself
newPtr->currentWord = newItem; // <-- save the copy in the list, not the argument
newPtr->link = NULL;
if(list->head == NULL)
{
list->head = newPtr;
}else{
sent* current = list->head;
while(current->link != NULL){
current = current->link;
}
current->link = newPtr;
}
list->count++;
} // insertList
For proper cleanup and to avoid memory leaks, the following freeList should be called for each list pointer returned by createList and filled by insertSentList.
void freeList(LISTS *list)
{
sent *temp = list->head;
while(temp != NULL)
{
sent *next = temp->link;
free(temp->currentWord->ch);
free(temp->currentWord);
free(temp);
temp = next;
}
free(list);
}
so, I just coded a Insertion Sort to sort a linked list (wiith dummy cell).
It works pretty good, but, at the end of the code, If I use free() in a pointer that I used as auxiliar, It's free also one of my cell (the last one it pointer in the loop).
So in order to avoid it free my cell, first I'm pointing de pointer to NULL, but here's my question: Wasn't it supposed to free just the pointer and not my cell if I didn't pointed NULL?
Here's my function
void
insertSort(cel *lst){
cel *temp = NULL;
cel *ordenado = lst->prox;
while(ordenado){
cel *valorOrdenando = ordenado->prox;
// removendo o valorOrdenado da lista
ordenado->prox = valorOrdenando->prox;
for (cel* i = lst; i != ordenado->prox; i = i->prox)
{
if (valorOrdenando->valor <= (i->prox)->valor || i->prox == ordenado->prox){
temp = i->prox;
i->prox = valorOrdenando;
valorOrdenando->prox = temp;
break;
}
}
ordenado = ordenado->prox;
}
// and here is where I point to NULL, otherwise I lost a cell
temp = NULL;
free(temp);
}
Here's the other part of the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct cel {
int valor;
struct cel *prox;
}typedef cel;
void inserir (cel **lista, int x) {
cel *temp = NULL, *aux = *lista;
temp = malloc(sizeof(cel));
temp->valor = x;
temp->prox = NULL;
if (*lista == NULL)
*lista = temp;
else {
for (; aux->prox != NULL; aux = aux->prox);
aux->prox = temp;
}
}
void imprimir(cel *lista) {
for (cel *aux = lista; aux != NULL; aux = aux->prox)
printf("%d ,", aux->valor);
printf("\n");
}
int main(){
cel *list = NULL;
inserir(&list, 3);
inserir(&list, 2);
inserir(&list, 1);
inserir(&list, 8);
inserir(&list, 6);
insertSort(list);
//bubbleSort(list->prox);
imprimir(list->prox);
return 0;
}
How should I code so that I didn't need to user *temp = NULL and why Is it happening currently??
You have a misconception about how pointers work in C. When you declare a pointer, it is just like declaring any other variable.
If you declare a pointer locally (inside a function, without a modifier such as static) the memory position it occupies will be handled by lower layers that the language C abstracts for you. One common implementation is to use a stack, when you declare a variable locally it will be pushed onto the stack when the function is called and will be popped out of the stack once the function returns, so there is no need to worry about deallocating your pointers.
However, a pointer points to a certain memory position and when you use a function like malloc it allocates a free memory block for you and the pointer points to the first position of the block. Now that block will only return to the free block list when you free it. So once you have finished using that memory location you should free it.
When you did:
temp = NULL;
free(temp);
You were trying to free the NULL memory position, which does not make sense.
So you are only going to free a memory once you do not need it anymore.
I suggest you search more about variables and pointers in the C language, this link might help you:
enter link description here
I have created a linked list in C that is used to store data which is then modified as required. In creating the linked list I have used the following
struct car_elements
{
char car_rego[7];
double time_parked;
struct car_elements *next;
};
typedef struct car_elements car;
/* Defined as global variable to hold linked list */
car *head = NULL;
car *SetupCars()
{
car *ptr = head;
car *new_car = NULL;
new_car = (car*) malloc(sizeof(car));
if (!new_car)
{
printf("\nUnable to allocate memory!\n");
exit(1);
}
strcpy(new_car->car_rego, "empty");
new_car->time_parked = time(NULL);
new_car->next = NULL;
if (ptr == NULL)
{
return (new_car);
}
else
{
while (ptr->next)
{
ptr = ptr->next;
}
ptr->next = new_car;
return (head);
}
}
From main I call the following to create the linked list
for(int i = 0; i<TOTAL_CARS; i++) {
head = SetupCars(head);
}
The problem is that now I have a memory leak - Is there a better way to create a fixed size linked list. At the end of the program running I can
free(head);
However I cannot call within SetupCars method
free(new_car);
I could create new_car as a global variable I guess and free it at the end of the program but I cannot help but feel there is a better way to do it. I don't think global variables are evil if used properly however I would appreciate some advice.
WHy not just free it at the end? SOmething like this:
car *tofree;
car *ptr = head;
while(ptr) {
tofree = ptr;
ptr = ptr->next;
free(tofree);
}
You need a function to free the entire list, like:
void free_cars(car*p) {
while (p != NULL) {
car* nextp = p->next;
free (p);
p = nextp;
}
}
So you would call
free_cars (head);
head = NULL;
Perhaps even by having a macro
#define DELETE_CARS(CarsVar) do { \
free_cars(CarsVar); CarsVar = NULL; } while(0)
then just write DELETE_CARS(head); later in your code.
And indeed, manual memory management is painful, you need to avoid memory leaks. Tools like valgrind can be helpful. And you could consider instead to use Boehm's garbage collector, so use GC_MALLOC instead of malloc and don't bother freeing memory.... Read more about garbage collection.
Keep car *head as a global var. For SetupCars:
void SetupCars() /* void will do, unless you want a copy of the new "car" */
{
car *new_car = NULL;
new_car = malloc(sizeof *new_car); /* don't need to cast return value of malloc */
/* do checks and setup new_car... */
if (head == NULL) /* first element */
{
head = new_car;
}
else /* easier to add new_car as the FIRST element instead of last */
{
new_car->next = head;
head = new_car;
}
}
From main you create the linked list the same way:
for(int i = 0; i<TOTAL_CARS; i++) {
SetupCars(); /* without any arguments */
}
Then at the end, you loop through the list and free the objects. As Manoj Pandey posted in his answer:
car *tofree;
car *ptr = head;
while(ptr) {
tofree = ptr;
ptr = ptr->next;
free(tofree);
}
I trying to write a queue(String Version) program in C by using linked lists.
Here is the structure:
struct strqueue;
typedef struct strqueue *StrQueue;
struct node {
char *item;
struct node *next;
};
struct strqueue {
struct node *front;//first element
struct node *back;//last element in the list
int length;
};
I creates a new StrQueue first
StrQueue create_StrQueue(void) {
StrQueue q = malloc(sizeof (struct strqueue));
q->front = NULL;
q->back = NULL;
q->length = 0;
return q;
}
makes a copy of str and places it at the end of the queue
void push(StrQueue sq, const char *str) {
struct node *new = malloc(sizeof(struct node));
new->item = NULL;
strcpy(new->item,str);//invalid write size of 1 ?
new->next = NULL;
if (sq->length == 0) {
sq->front = new;
sq->back = new;
} else {
sq->back->next = new;
sq->back = new;
}
sq->length++;
}
frees the node at the front of the sq and returns the string that was first in the queue
char *pop(StrQueue sq) {
if (sq->length == 0) {
return NULL;
}
struct node *i = sq->front;
char *new = sq->front->item;
sq->front = i->next;
sq->length --;
free(sq->front);
return new;
}
I got invalid write size of 1 at strcpy(new->item,str); I dont understand why I got this error.
Can anyone tell me why and tell me how should I fix it? Thanks in advance.
Okay, first things first, in the answer below I am NOT fixing your doubly linked list concepts, I am just showing you how you should fix the code above within the scope of your question. You may want to look into how doubly linked lists are done.
In:
void push(StrQueue sq, const char *str) {
struct node *new = malloc(sizeof(struct node));
new->item = NULL;
The next statement is wrong:
strcpy(new->item,str);
There are two ways you can solve it:
Make sure that *str is a valid pointer outside of the list management context while the list is being used.
Let the list manage the string allocation (and possibly deallocation).
is the quick and dirty method, it's easier to debug later but larger codebase makes it cumbersome.
cleaner looking code, but requires initial setup discipline, you should create object (string) management routines in addition to list management routines. can be cumbersome in its own right.
CASE 1: const char *str is guaranteed to be valid for life of StrQueue (this is what you are looking for really)
It should be:
new->item = str;
Here we assume str was a dynamic string allocated elsewhere
Now, in pop when you pop off the string you are okay. because the pointer you are returning is still valid (you are guaranteeing it elsewhere)
CASE 2: const char *str is not guaranteed to be valid for life of StrQueue
Then use:
new->item = strdup(str);
Now, in pop when you pop off the string you can either
de-allocate the strdup and not return anything, (not quite the same things as you did)
pass a container pointer to pop where contents of item are copied (clean)
return the popped off pointer, but you must deallocate it separately when you are done with it (ugly)
Which would make your pop function one of the following:
Case 2.1:
void pop(StrQueue sq) {
if (sq->length == 0) {
return NULL;
}
struct node *node = sq->front;
sq->front = node->next;
sq->length--;
free(node->item);
free(node);
}
Case 2.2:
char *pop(StrQueue sq, char *here) {
if (sq->length == 0) {
return NULL;
}
struct node *node = sq->front;
sq->front = node->next;
sq->length--;
strcpy(here, node->item);
free(node->item);
free(node);
}
Case 2.3:
char *pop(StrQueue sq) {
char *dangling_item = NULL;
if (sq->length == 0) {
return NULL;
}
struct node *node = sq->front;
sq->front = node->next;
sq->length--;
dangling_item = node->item;
free(node);
return dangling_item;
}
I got invalid write size of 1 at strcpy(new->item,str); I dont understand why I got this error. Can anyone tell me why and tell me how should I fix it?
Why:
This code:
new->item = NULL;
strcpy(new->item,str);//invalid write size of 1 ?
You're not suppose to pass a null pointer to the first argument, it should be a pointer to allocated memory. The reason why you're getting this error message, I can imagine, is because the implementation of strcpy probably looks like this:
for (int i = 0; str2[i]; i++) str1[i] = str2[i];
And in the first iteration of the for loop, it writes to address 0 (a read-only section of memory) - this gives you the invalid write of size 1. I'm not sure, however, why you are only getting a size of 1, though (I would imagine it would be the entire size of the string). This could be because either a) str is only of size 1 or b) because the signal, SIGSEGV stops the program.
How to fix:
Allocate space for new->item before calling strcpy, like this:
new->item = malloc (strlen (str) + 1); // + 1 for null-terminating character
But you could probably include some error checking, like this:
int len = strlen (str) + 1;
if (len){
new->item = malloc (len);
if (!new->item){
return;
}
}
I'm currently playing with linked lists, and I've put together the following code for testing purposes.
First I'd like to point out, I'm aware of my unusual list setup, it was just a test, to get a not upside down list. My actual "problem" now is, that I don't seem to have any memory leaks once the program terminates, although I'm not freeing the list. I'm using drmemory on Windows for analyzing, and it always worked nicely. If I put some other mallocs in this code, it notices the not freed memory. Why doesn't it notice the list?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ----------------------
typedef struct Item
{
char name[10];
struct Item *next;
} Item;
Item *items = NULL;
Item *items_add(const char* name)
{
Item *new = malloc( sizeof(Item) );
strcpy(new->name, name);
new->next = NULL;
if(items == NULL)
{
items = new;
}
else
{
Item *iter = items;
while(iter->next != NULL)
{
iter = iter->next;
}
iter->next = new;
}
return new;
}
void items_rem(const char* name)
{
if(items == NULL)
return;
Item *iter = items, *prev;
do
{
if(strcmp(iter->name, name) == 0)
{
prev->next = iter->next;
free(iter);
break;
}
prev = iter;
iter = iter->next;
}
while(iter->next);
}
// ----------------------
int main(void)
{
items_add("Item1");
items_add("Item2");
items_add("Item3");
items_add("Item4");
items_rem("Item3");
for(Item *iter = items; iter != NULL; iter = iter->next)
{
printf("%s\n", iter->name);
}
/*
Output:
Item1
Item2
Item4
*/
}
The reason, I can think of is that Item *items = NULL 'items' is a global variable. So, as far as the memory leak checking tool is concerned, the memory is still accessible from the code, so it may be assuming that you still need that memory.
Atleast IBM Rational Purify works in this way. In IBM Rational Purify, you can select the option to show "Memory in use" and it will display this pointer and number of bytes held by it.
Please note that a memory is considered leaked only when there are no pointer variables containing that address and it has not been freed also.
For Ex:
int main()
{
function();
}
int function()
{
char *ptr = NULL;
ptr = malloc(10);
return 0;
}
Now, in the above example, once you return from function, there is no way for you to access variable ptr. So, the memory allocated for ptr is definitely lost
drmemory doesn't show reachable allocations by default, try running drmemory with the -show_reachable option set