C: Help finding memory faults - c

My program is written in C and it is a disk emulator. I finished writing it and it runs when I comment out certain lines of my test program, but I get a memory error where I un-comment them. I suspect it is with my char* 's.
The line I comment out (and where the program crashes) is
free(buffer);
where buffer is the char* that the string of bytes that was read into from the disk. It was initially allocated 30 bytes using malloc.
char* buffer = (char *) malloc(sizeof(char) * 30);
There is too much to just post it all here, so I am going to put the parts where I am writing/copying to char* 's in the hopes that someone will see what I am doing wrong.
I don't think it is anything too complicated, I am just not familiar enough with C the recognize obvious memory mistakes.
// In the event of a cache miss:
// block_buffer to pass to add_cache_entry
char cMissBuffer[BLOCK_SIZE];
// read content of block from disk
fread(cMissBuffer,sizeof(char),BLOCK_SIZE,diskEntity.pBlockStore);
// add to cache
if(1==add_cache_entry(i,cMissBuffer)) return 1;
.
.
.
// some of what is in add_cache_entry
int add_cache_entry(int v, char *block_buffer)
{
// ...
// construct a new queue element
QueueElement *block_to_cache = (QueueElement*)malloc(sizeof(QueueElement));
block_to_cache->blkidx = v;
block_to_cache->content=(char*)malloc(BLOCK_SIZE);
strcpy(block_to_cache->content,block_buffer);
// ...
}
In the test, BLOCK_SIZE is 5, QueueElement is a struct, content is a char* with BLOCK_BYTES of info.
Here is an excerpt from running the executable (dumping the queue)...I think that the lack of a '\0' could have something to do with the issue...
after adding cache entry (5):
DUMP:
BLOCK 5 FLAG:0 CONTENT:222220000000
BLOCK 4 FLAG:0 CONTENT:222220000000
BLOCK 3 FLAG:0 CONTENT:000000000000
BLOCK 2 FLAG:0 CONTENT:000000000000
BLOCK 1 FLAG:1 CONTENT:11100
I think I get extra space because malloc allocates more space than I require, but I read that is normal.
Any thoughts?

A probable cause for the behaviour is that strcpy() requires the source string to be null terminated, which is not the case here as fread() does not append a null terminator for you (nor could it in this case as fread() is reading the exact buffer size). strcpy() also appends a null terminator which means the strcpy() call will definitely be writing beyond the block_to_cache->content buffer.
If the data is not be used as a C style string use memcpy() to copy the data instead:
memcpy(block_to_cache->content, block_buffer, BLOCK_SIZE);
Other points:
Check the return value of fread(), to ensure it successfully populated the buffer before attempting to use it.
it is unnecessary to cast the return value of malloc() (see Do I cast the result of malloc?).
check return value of malloc() to ensure memory was successful allocated.
sizeof(char) is guaranteed to be one so can be removed from argument to malloc().

Related

Move pointer and realloc, C

I'm trying to code a buffer for an input file. The Buffer should always contain a defined amount of data. If a few bytes of the data were used, the buffer should read data from the file until it has the defined size again.
const int bufsize = 10;
int *field = malloc(bufsize*sizeof(int)); //allocate the amount of memory the buffer should contain
for(i=0;i<bufsize;++i) //initialize memory with something
*(field+i) = i*2;
field += 4; //Move pointer 4 units because the first 4 units were used and are no longer needed
field= realloc(field,bufsize*sizeof(int)); //resize the now smaller buffer to its original size
//...some more code were the new memory (field[6]-field[9]) are filled again...
Here is a short example of how I'm trying to do it at the moment (without files, because this is the part thats not working), but the realloc() always returns NULL. In this example, the first 4 units were used, so the pointer should move forward and the missing data at the end of the memory (so that it will again contain 10 elements) should be allocated. What am I doing wrong?
I would be very thankful if someone could help me
You need memmove() instead
memmove(field, field + 4, (bufsize - 4) * sizeof(*field));
you don't need to realloc() because you are not changing the size of the buffer, just think about it.
If you do this
field += 4;
now you lost the reference to the begining of field so you can't even call free on it, nor realloc() of course. Read WhozCraig comment for instance.
Doing realloc() for the same size doesn't make that much sense.
Using realloc() the way you do causes some other problems, for instance when it fails you also run into the same problem, you loose reference to the original pointer.
So the recommended method is
void *pointer;
pointer = realloc(oldPointer, oldSize + nonZeroNewSize);
if (pointer == NULL)
handleFailure_PerhapsFree_oldPointer();
oldPointer = pointer;
So the title of your question contains the answer to it, what you need is to move the data from offset 4 * sizeof(int) bytes to the begining of the pointer, for which memmove() is the perfect tool, notice that you could also think of using memcpy() but memcpy() cannot handle the case of overlapping data, which is your case.
Your problem should be named as Cyclic Buffer.
You should call malloc() just once when opening file and once free() when you close it.
You don't need to call realloc() at all. All is necessary is advaning pointer by amount of read data, wrapping its value around size of buffer and replacing old data with new data from file.
Your problem with realloc(): you must pass same pointer to it which was previously returned from malloc() or realloc() without offsetting it!

dealing with pointers in realloc?

Please look at the following code
char *line = (char *) malloc(100);
char *newline,*source = line;
int size=100;
newline = realloc ( line , size +=size);
// assuming that newline has been successfully assigned the demanded memory and line is freed
Now my question here is that can i write in future expression like
source = newline +( line - source );
I am having doubt in mind because i am using the line pointer which is freed after the successful operation of the realloc() but My program ( this only a snippet from it ) is
still working?so is it safe to use line pointer after realloc() has done?
No, it's not safe to use the line pointer after realloc is done. realloc changes the size of the block pointed to by line. If the size increases, the old location may not have enough contiguous space to accommodate the new larger block. So the location of the block in the memory changes. Use the pointer returned by realloc.
If the old location does not have enough contiguous space for the larger block requested by the user, realloc tries to find a new block of the required size (like malloc), copies the elements from the old block and frees the old block.
If realloc fails, the old pointer is valid and must be freed. If realloc succeeds, the old pointer is considered invalid and should not be freed.
Also, the fact that your program is working is not always a good way to check if something is correct. For example, if you declare int a[10] and you access a[10] or a[11] it may not fail most of the time but it's still undefined behaviour.
so is it safe to use 'linepointer afterrealloc()` has done?
No, because realloc() may free your input buffer while making the new one(if new one is larger than the previous size). And realloc would copy the previous user data from the old buffer into new buffer. So user should use the new buffer as it contains all older information not the old one.
This is about realloc()
void *realloc(void *p, size_t size) realloc changes the size of the
object pointed to by p to size. The contents will be unchanged up to
the minimum of the old and new sizes. If the new size is larger, the
new space is uninitialized. realloc returns a pointer to the new
space, or NULL if the request cannot be satisfied, in which case *p is
unchanged.

runtime error in a function copying from string to allocated memory

I have some second thoughts about the following C puzzle question. I'm curious what more experience C programmers may think... Have a look at the sample code:
char * strdup (const char * s) {
char * buf;
int len;
assert(s != NULL);
len = strlen(s);
buf = (char *) calloc(len + 1, sizeof(char));
memcpy(buf, s, len);
return buf;
}
The proposed implementation of strdup() above contains a runtime error that may NOT appear consistently with each invocation. Which one of the following accurately describes this error?
The possible answers to this one are:
1 The arguments to calloc() do not cause enough memory to be allocated for storing the contents of s.
2 If memory is scarce, calloc() may fail and return NULL. The code does not anticipate this condition.
3 memcpy() may corrupt data if used to copy ASCII strings.
4 buf is never NUL-terminated, and therefore cannot be used by C library functions affecting strings.
5 The function returns a pointer to dynamic memory. This practice should be avoided and always constitutes a memory leak.
What I've thought is that the correct answer is 2 but it is more because the other answers seem incorrect to me than because answer 2 is the immediate right one.
answer 1 seems incorrect as calloc reserves enough memory (len+1) to end the string appropriately,
I dont know anything about what is written in answer 3,
answer4: memcpy copies the content of s to buf leaving the last byte equal to 0 (copies len bytes, note that previos call to calloc filled the last byte with 0). Therefore, this answer is incorrect,
answer 5: ?
What do you think?
Thanks in advance...
Correct answer is 2 & 5.
#2 because memory allocation functions can fail and you must check their return values.
#5 because, unless you document the fact that your function dynamically allocates returned buffer caller cannot know that they have to free the returned buffer.
#1 is not correct because, as you rightly said calloc allocates memory required by string + extra byte required for NULL termination.
#3 is not correct because it is not true, memcpy simply copies data from source to destination. It is not affected by what is stored in that memory.
#4 is not correct, because calloc zeroes out the allocated memory.

Malloc has junk for C string?

I'm new to C, so feel free to correct mistakes.
I have some code that somewhat goes like this:
// some variables declared here like int array_size
char* cmd = (char*)malloc(array_size*sizeof(char));
for(;;){
// code here sets cmd to some string
free(cmd);
array_size = 10;
cmd = (char*)malloc(array_size*sizeof(char));
// print 1
printf(cmd);
printf("%d\n", strlen(cmd));
// repeat above for some time and then break
}
So I do the loop for a while and see what it prints. What I expected was every time the string would be empty and the length would be 0. However, that is not the case. Apparently sometimes malloc gets memory with junk and prints that out and that memory with junk has a length != 0. So I was thinking about solving this by setting all char in a new char string to '\0' when malloc returns; however, I'm pretty sure I just did something wrong. Why is it even after I free the string and do a whole new malloc that my string comes with junk unlike the first malloc? What am I doing wrong?
malloc just allocated the memory and nothing more. It has no promises about what is in the memory. Specifically, it does not initialize memory. If you want allocated memory to be zeroed out, you can either do it manually with memset or simply call calloc (which is essentially malloc with zeroing out of memory).
malloc does not initialise the memory. You are just lucky the first time around.
Also if it is junk and contains a % symbol you are going to have other problems.
No you did nothing wrong - malloc does not guarantee the memory will be set to 0, only that it belongs to your process.
In general setting newly allocated memory to zero in unneeded so in C it is never explicitly cleared which would take several clock cycles.
There is a rather convenient method 'memset' to set it if you need
Your code segment has, at a minimum, the following problems.
You don't ever need to multiply by sizeof(char) - it's always one.
You cast the return value of malloc. This can hide errors that would otherwise be detected, such as if you forget to include the header with the malloc prototype (so it assumes int return code).
malloc is not required to do anything with the memory it gives you, nor will it necessarily give you the same block you just freed. You can initialise it to an empty string with a simple *cmd = '\0'; after every malloc if that's what you need.
printf (cmd) is dangerous if you don't know what cmd contains. If it has a format specifier character (%), you will get into trouble. A better way is printf ("%s", cmd).

Using strtok() on an allocated string?

Is there anything I should know about using strtok on a malloced string?
In my code I have (in general terms)
char* line=getline();
Parse(dest,line);
free(line);
where getline() is a function that returns a char * to some malloced memory.
and Parse(dest, line) is a function that does parsing online, storing the results in dest, (which has been partially filled earlier, from other information).
Parse() calls strtok() a variable number of times on line, and does some validation.
Each token (a pointer to what is returned by strtok()) is put into a queue 'til I know how many I have.
They are then copied onto a malloc'd char** in dest.
Now free(line)
and a function that free's each part of the char*[] in dest, both come up on valgrind as:
"Address 0x5179450 is 8 bytes inside a block of size 38 free'd"
or something similar.
I'm considering refactoring my code not to directly store the tokens on the the char** but instead store a copy of them (by mallocing space == to strlen(token)+1, then using strcpy()).
There is a function strdup which allocates memory and then copies another string into it.
You ask:
Is there anything I should know about
using strtok on a malloced string?
There are a number of things to be aware of. First, strtok() modifies the string as it processes it, inserting nulls ('\0') where the delimiters are found. This is not a problem with allocated memory (that's modifiable!); it is a problem if you try passing a constant string to strtok().
Second, you must have as many calls to free() as you do to malloc() and calloc() (but realloc() can mess with the counting).
In my code I have (in general terms)
char* line=getline();
Parse(dest,line);
free(line);
Unless Parse() allocates the space it keeps, you cannot use the dest structure (or, more precisely, the pointers into the line within the dest structure) after the call to free(). The free() releases the space that was allocated by getline() and any use of the pointers after that yields undefined behaviour. Note that undefined behaviour includes the option of 'appearing to work, but only by coincidence'.
where getline() is a function that
returns a char * to some malloced
memory, and Parse(dest, line) is a
function that does parsing online,
storing the results in dest (which
has been partially filled earlier,
from other information).
Parse() calls strtok() a a variable
number of times on line, and does some
validation. Each token (a pointer to
what is returned by strtok()) is put
into a queue 'til I know how many I
have.
Note that the pointers returned by strtok() are all pointers into the single chunk of space allocated by getline(). You have not described any extra memory allocation.
They are then copied onto a malloc'd
char** in dest.
This sounds as if you copy the pointers from strtok() into an array of pointers, but you do not attend to copying the data that those pointers are pointing at.
Now free(line) and a function that
free's each part of the char*[] in
dest,
both come up on valgrind as:
"Address 0x5179450 is 8 bytes inside a block of size 38 free'd"
or something similar.
The first free() of the 'char *[]' part of dest probably has a pointer to line and therefore frees the whole block of memory. All the subsequent frees on the parts of dest are trying to free an address not returned by malloc(), and valgrind is trying to tell you that. The free(line) operation then fails because the first free() of the pointers in dest already freed that space.
I'm considering refactoring my code
[to] store a copy of them [...].
The refactoring proposed is probably sensible; the function strdup() already mentioned by others will do the job neatly and reliably.
Note that after refactoring, you will still need to release line, but you will not release any of the pointers returned by strtok(). They are just pointers into the space managed by (identified by) line and will all be released when you release line.
Note that you will need to free each of the separately allocated (strdup()'d) strings as well as the array of character pointers that are accessed via dest.
Alternatively, do not free line immediately after calling Parse(). Have dest record the allocated pointer (line) and free that when it frees the array of pointers. You still do not release the pointers returned by strtok(), though.
they are then copied on to to a malloc'd char** in dest.
The strings are copied, or the pointers are copied? The strtok function modifies the string you give it so that it can give you pointers into that same string without copying anything. When you get tokens from it, you must copy them. Either that or keep the input string around as long as any of the token pointers are in use.
Many people recommend that you avoid strtok altogether because it's error-prone. Also, if you're using threads and the CRT is not thread-aware, strtok will likely crash your app.
1 in your parse(), strtok() only writes '\0' at every matching position. actually this step is nothing special. using strtok() is easy. of course it cannot be used on read-only memory buffer.
2 for each sub-string got in parse(), copy it to a malloc()ed buffer accordingly. if i give a simple example for storing the sub-strings, it looks like the below code, say conceptually, though it might not be exactly the same as your real code:
char **dest;
dest = (char**)malloc(N * sizeof(char*));
for (i: 0..N-1) {
dest[i] = (char*)malloc(LEN);
strcpy(dest[i], sub_strings[i]);
NOTE: above 2 lines could be just one line as below
dest[i] = strdup(sub_string[i]);
}
3 free dest, conceptually again:
for (i: 0..N-1) {
free(dest[i]);
}
free(dest);
4 call free(line) is nothing special too, and it doesn't affect your "dest" even a little.
"dest" and "line" use different memory buffer, so you can perform step 4 before step 3 if preferred. if you had following above steps, no errors would occur. seems you made mistacks in step 2 of your code.

Resources