C memory free confusion - c

I have a short question about my code. I've created two situation or examples for testing.
example 1:
char *arr[1000000];
int i = 0;
for (; i < 1000000; i++){
char *c = (char *) calloc(1, sizeof(char) * 10);
free(c);
}
example 2:
char *arr[1000000];
int i = 0;
for (; i < 1000000; i++){
char *c = (char *) calloc(1, sizeof(char) * 10);
arr[i] = c;
free(arr[i]);
arr[i] = NULL;
}
The differents in examples: putting in an array before free'ing the memory.
When I run example 1 it free's all memory. When I run example 2 it doesn't free all memory.
I've searched and looked but couldn't figure it out.
Why is the result of example 2 different then example 1?
My common sense tells me example 1 and 2 should result the same, but in practice it doesn't. I use linux top for checking memory usage.

The result are the same. I'm not sure why you think there are differences.

It is caused by demand-paging. The process has the address space for the array (that is: pagetable entries exist for it) but there is no memory attached to it (yet). The loop assigns to (eventually) all the memory pages that belong to array[], so at the end of the loop all pages have been "faulted-in".
As a proof of concept, you can replace the loop with:
for (; i < 1000000; i++){
arr[i] = "hello, world!";
}
And the result will probably be (almost) the same as in snippet#2

Both are the same.
Since you use top for reading memory the difference can be explained with compiler optimizations. For example, the array in example one can be completely optimized out.
For checking memory issues, you should use valgrind or a similar tool.

Related

Pointer Arithmetic in C while equating two pointers

Kindly note that I had gone through several questions in stackoverflow related to pointers but I could not get similar kind of question which I am about to ask. It may be that question already exists and I dont know proper tag to search. here is my doubt in C programming.
First program
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int i,j;
int **p = (int **)malloc(2 * sizeof(int *));
p[0] = (int *)malloc(2 * sizeof(int));
p[1] = p[0];
for(i = 0; i < 2; i++)
for(j = 0; j < 2; j++)
p[i][j] = i + j;
printf("%d",p[0][0]);
return 0;
}
Output is 1
Second Program
7th line is changed to
p[1] = (int *)malloc(2 * sizeof(int));
Output is 0;
Both the programs almost look similar but they are giving different results. I am just not able to understand whats going underneath. Can anyone please help.
p[1] = p[0]; makes p[1] (which is a pointer) point to the same memory as p[0] points to.
p[1] = (int *)malloc(2 * sizeof(int)); dynamically allocates new memory and lets p[1] point to that.
So if you modify p[1][i] you are modifying the same object as p[0][i] in the first, but not the second, case.
Long story short. In the first case. There is a single memory location allocated where the data is held. In the second case. Memory is allocated twice so 2 separate memory locations exist holding separate data. Hope you can figure out the rest

find middle point in c array

I am studying C programming. I want to find a middle point of array without knowing about length of it. If length of array is 6, middle point must be 4th, but I have an error and I don't know what it is. Here is my code:
int *a =(int *) malloc(sizeof(int) * n);
int i;
for( i = 0; i < sizeof(a); i++)
scanf("%d",&a[i]);
Anyone can help, thank you.
scanf is reading into an address, so:
scanf("%d",a[i])
should really be:
scanf("%d", &a[i])
And do not forget to free the memory when you're done. (For tiny applications like this it does not matter, but it is a good habit if you get used to it when you are stepping out from the learning phase and getting into the real life programming)
And also: sizeof(a) is the size of the pointer, not the size of the memory allocated the pointer points to (as correctly pointed out in the other answer).
This is wrong: for( i = 0; i < sizeof(a); i++). Here sizeof(a) will return size of the int pointer, likely 4 or 8 on your system. In general, don't use sizeof to determine the element count of an array, use separate variable instead.
You'll want to use for( i = 0; i < n; i++) instead.

Trouble allocating memory in 2Darray of a structure

I am trying to develop the TicTacToe game in C and I am using the following structures.The myboard->a member is used to store 'X' or 'O' ,meaning the move a player has made in the same coordinates as the board , ie. 'X' in (1.1) or 'O' (3.1)
typedef struct{
int** a;
int size;
}_board;
typedef _board* board;
board myboard =(board) malloc(sizeof(board));
scanf_s("%d", &(myboard->size));
Size=is the size of the TicTacToe board nxn.
myboard->a =(int**)malloc(myboard->size*sizeof(char *));
if (myboard->a = NULL)
{
printf("ERROR!!!");
}
Until this point everything seems to work but when a try to allocate memory as you see bellow, a get a segmentation fault.
int i;
for (i = 0; j<myboard->size; i++)
{
myboard->a[i] = malloc(sizeof(char));
if (myboard->a[i] == NULL)
{
printf("ERROR");
}
}
I am using free for its malloc at the end of me program.
Thanks, in advance for any answer , and sorry for my bad english. Any help is apreciated.
I don't really understand why you are using a int** variable for storing your board data, when you could just use one simple int*, which you could later assign with malloc(3) as in:
int* b_data;
int b_size = 9;
b_data = malloc(b_size * sizeof(int));
// ... Your code
free(b_data);
If however, you really want to use a int** variable, you could do something like:
int** b_data;
int b_size_x = 3;
int b_size_y = 3;
int i;
b_data = malloc(b_size_x * sizeof(int*));
for(i = 0; i < b_size_x; i++)
*(b_data + i) = malloc(b_size_y * sizeof(int));
// ... Your code where you access your array of size_x containing
// arrays of size_y of int typed "cells"
for(i = 0; i < b_size_x; i++)
free(*(b_data + i));
free(b_data);
But this is really unnecessarily complicated, and I would dis-advise from doing so unless for learning purposes: in most cases, the allocated memory will be contiguous, so the second solution will allocate a nearly identical structure in memory, but will be less efficient (the "2D" array solution takes b_size_x times sizeof(int*) more memory), and the first solution will be simpler to read/write (so less prone to bugs, and easier to maintain).
Concerning your code, your problem is that myboard->a is NULL right after the "check" (which is in fact an allocation - note that the "ERROR" is never shown because myboard-> is then NULL, which evaluate to 'false'.):
if (myboard->a = NULL)
which should be:
if (myboard->a == NULL)
In addition, as pointed by #WhozCraig in his comment on your post, you might want to use i in the condition of your for loop, rather than j; and you also probably want to use int and int* types rather than char and char* types respectively in your malloc(s), since the a member of the board structure is an int**. Oh and also, think about putting newlines after your printf(3) strings, or use puts(3).

freeing substring without doing double free in c

Yesterday I asked a similar question regarding how to free allocated memory for a sub-string. Now I have one more question regarding the same problem (involving a set of conditions), how could I free the following sub-string without doing double free?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct st_ex {
char product[16];
float price;
};
struct st_temp {
char *prod;
};
char *temp = NULL;
// from stackoverflow
char* substr( const char* source, size_t start, size_t end )
{
char* dest = malloc( end - start + 1) ;
memcpy( dest, &source[start], end - start ) ;
dest[end - start] = 0 ;
return dest ;
}
int main()
{
struct st_ex structs[] = {{"mp3 player", 2.0f}, {"plasma tv", 20.0f},
{"notebook", 10.0f}, {"smartphone", 49.9f},
{"dvd player", 10.0f}, {"matches", 0.2f }};
struct st_temp **temp_struct;
size_t j, i;
temp_struct = malloc(sizeof *temp_struct * 6);
for (j = 0; j < 6; j++)
temp_struct[j] = malloc(sizeof *temp_struct[j]);
size_t structs_len = sizeof(structs) / sizeof(struct st_ex);
// NOTE: that structs_len may vary in size - not just 6
for(i=0; i<structs_len; i++){
if (i == 0)
temp_struct[i]->prod = "+";
else if(i == 1)
temp_struct[i]->prod = "Bar";
else if(i == 5)
temp_struct[i]->prod = "Foo";
else {
temp = substr(structs[i].product, 0, 4);
temp_struct[i]->prod = temp;
}
}
for(i=0; i<6; i++ )
printf("%s\n",temp_struct[i]->prod);
for(i = 0; i < 6; i++ ){
/* can I do something like this? */
/*if (i != 0 || i != 1 || i != 5)*/
free(temp_struct[i]->prod);
free(temp_struct[i]);
}
free(temp_struct);
return 0;
}
The problem is that sometimes you set temp_struct[i]->prod to a quoted string ("Bar") which you cannot free and sometimes to the result of a substr call, which you must free.
The easiest solution is to always set it to a string that you must free.
temp_struct[i]->prod = new_string("Bar");
where
char* new_string( const char* source )
{
char* dest = malloc( strlen(source) + 1 ) ;
strcpy(dest, source);
return dest ;
}
or, you have to keep track if you need to free or not
struct st_temp {
char *prod;
int prod_must_be_freed;
};
set prod_must_be_freed to 0 or 1 and check that before you free.
And, finally, the whole thing would be improved by using functions to manipulate these structs rather than just fiddling with them directly. Then you could make a free_st_temp(st_temp*) that checked if prod should be freed, and then freed the struct. Your loop would be
for(i = 0; i < 6; i++ ){
free_st_temp(temp_struct[i]);
}
Substrings do not take up extra memory. They are pointers to parts of already existing strings.
Yes, given that your substr is allocating the memory for the substring with malloc, it's reasonable (necessary, really) to free that memory when you're done with it. That said, I think the way you're doing things right now is extremely fragile and error-prone (to put it mildly). If you have any choice at all, I'd allocate the strings for all the prod members the same way -- if you can't allocate them all statically, then allocate them all dynamically, so when you're freeing structures, you can do so uniformly. Trying to assure that you keep the subscripts matched up to free prod if and only if it was allocated dynamically is practically begging for trouble.
You have an additional problem. When you do temp_struct[i]->prod = "Bar"; You are assigning a const char* to prod. That pointer cannot be freed (the most likely outcome is a crash). So if you want to have your code set up this way such that prod can point to either dynamic memory that you got from malloc or to a constant string literal, you need to also keep track of which one it is and only free the dynamic memory.
The condition in your comment would technically work, but would be very poor form. The best idea is to not mix and match string types in the same pointer. But if you insist on doing it that way, then an improvement would be to add another variable to your struct that is set true when prod needs to be freed and false when it does not.
Yes, although you will want to uncomment that if, and change the conditions in the if to be joined with && rather than || (otherwise it will always be true -- every number is either not equal to zero or not equal to one!)
The substrings stored in temp_struct[i]->prod for i other than 0, 1, and 5, were allocated inside the substr function with malloc, so you can and should deallocate them with free.
Similarly, each temp_struct element was allocated with malloc, and so can and should be deallocated with free.
I'm not sure where you think the double free would be coming from. Are you thinking that when you call free(tmp_struct[i]) the memory pointed to by tmp_struct[i]->prod will also be freed? That isn't the case. When you free a pointer to a structure that contains pointers, the memory for the structure's pointers themselves is deallocated (being that it is part of the structure), but the memory being pointed to by those pointers is not, and must be deallocated seperately (since it is external to the structure). Aside from the mistake in the if condition, the way you have it written is the correct way to do this.

To find the substring in a given text.. C programm

char *substring(char *text, int position, int length)
{
int i, j=0;
char *temp ;
for(i=position-1; i<position+length-1; i++)
{
temp[j++] = text[i];
}
temp[j] = '\0';
return temp;
}
Hi What is the error in the following code.. I am trying to run this on Fedora Machine.. And its giving me a run-time error "Segmentation Fault". What is this error all about.. and why is it giving this error..
Thanks..
temp is uninitialized.
You need to allocate memory for temp - currently it's just a dangling pointer. You can use malloc for this but note that the caller will need to ensure that this storage is subsequently freed.
For example:
char *substring(const char *text, int position, int length)
{
char *temp = malloc(length + 1);
int i, j;
for (i = position, j = 0; i < position + length; i++, j++)
{
temp[j] = text[i];
}
temp[j] = '\0';
return temp;
}
It means that your code has violated some restriction set up by the operating system, in this case you are writing to memory that you do not have the right to write to.
This is because your temp variable is just an uninitialized pointer, it doesn't contain the address of memory where you are allowed to write.
If you expect to write length + 1 characters, it must be pointing to at least that many bytes worth of space.
Since you expect to return the string, you need to either make it static (but that can be dangerous), or allocate the space dynamically:
if((temp = malloc(length + 1)) == NULL)
return NULL;
I am making a copy of the sub-string into another pointer, this is the just the simple way of finding one substring of a given string..
Hope i am that very simple way in the correct manner..
Also, The methods given by SysAdmin,, looks pretty complex ones, but still thanx for the suggestion.. I will try and learn those as well.. But if you can tell me whether i have implemented the very basic pattern searching algorithm correctly, then it would be very kind..
Thanks..
while the answer is obvious - i.e temp is not initialized,
here is a suggetion.
If your intention is to find a substring in another string,
few alternatives are,
1. use C strstr(...)
2. Robin-Karp method
3. Knuth-Morris-Pratt method
4. Boyer Moore method
Update:
Initialy I thought this question was related to finding the substring (based on the title).
Anyway, this looks like strchr() implementation.
It is obvious from the code that you missed to allocate / initialize the pointer *temp. It is pointing to nowhere.
You either have to use malloc or strdup and do the rest. But yeah , you may also want to explore using strncpy (null terminate) to simplify the code.

Resources