Hey everyone, I am getting a heap corruption error I cannot figure out.
char * c = (char *) malloc(1);
// main loop
_gcvt_s(c, 100, ball->get_X_Direction(), 10);
if(pushFont(c, (SCREEN_WIDTH - 30), (SCREEN_HEIGHT - 40), message, screen,
font, textColor) == false)
{
//return 1; // error rendering text.
}
// end main loop
free(c);
The above code is the only time I use c pointer, in _gcvt_s and pushFont() which simply accepts a char * as its first parameter, and puts the text on the screen. Other then that I do not use c. When I try to free c after the main loop (which I think I am supposed to do), I get an error saying Visual Studio has acquired an error with the heap (heap corruption).
Commenting out the call to pushFont I still receive the error.
Can anyone explain to me why freeing a character (the 1 byte I allocated on the heap) would give me a heap corruption?
Lastly my main loop does a lot of stuff, a buddy and I are making a pong game with WinSocket, the rest of the main body is the loop for the game. I didnt think it was necessary to post, but I will update my post with the entire main loop if it is necessary, but I believe I am just off with my understanding of malloc() and free().
Thanks all,
Doesn't _gcvt_s use the 2nd parameter as the max size of the allocated buffer? You allocate 1 byte but tell _gcvt_s there are 100. So it happily writes up to 100 bytes into the buffer corrupting your heap. Then the free crashes. Allocate 100 bytes if you are going to potentially access 100 bytes.
EDIT: It sounds like you need to learn how C stores and manipulates strings. C stores strings as individual bytes in contiguous runs of memory followed by an extra character to indicate the end of the string. This extra character has an ASCII value of 0 (not the character '0' which is ASCII 48). So if you have a string like "HELLO", it takes 6 bytes to store - one for each of the 5 letters and the terminator.
In order for _gcvt_s() to return the value to your buffer, you need to include enough bytes for the conversion and the extra terminating byte. In the case of _gcvt_s(), you are asking for 10 characters of precision. But you also have to reserve room for the decimal point, the potential negative sign.
According to this [documentation](http://msdn.microsoft.com/en-us/library/a2a85fh5(VS.80).aspx), there is a #define in the headers for the maximum necessary size of the buffer: _CVTBUFSIZE. The example there should help you with this issue.
According to the documentation I can find _gcvt_s() takes a buffer and the length of that buffer as the first two arguments.
errno_t _gcvt_s(
char *buffer,
size_t sizeInBytes,
double value,
int digits
);
Your malloc()ed buffer is 1 byte long, you tell _gcvt_s() it is 100 bytes long. I would start looking here.
Why do you need to use the heap? If all you need is space for 1 char can't you just use a local variable:
char c;
_gcvt_s(&c...
?
You need more than one byte to store a float. Allocate a more practical length than 1 byte...
You also really don't need the heap, try a (slightly oversized) 16-byte buffer and giving _gcvt_s the correct buffer length (instead of the magical 100 you are giving it). De-magic your constants whilst you are at it.
const unsigned int cuFloatStringLength = 16;
const unsigned int cuFloatStringPrecision = 10;
char c[cuFloatStringLength];
_gcvt_s( c, cuFloatStringLength, ball->get_X_Direction(), cuFloatStringPrecision );
The problem should then be gone.
Related
I have a file containing the strings of 3 chromosome, which I want to concatenate into one genome. And then I have to access this concatenated string across multiple threads (I use pthread_t). To to this I have to use pthread_mutex_lock when extracting the data, then I use strcat to concatenate the data which are extracted using the function fai_fetch using const char* and then I am saving the data as a char* (see below).
// genome_size the size of all the chromosomes together
// chr_total the number of chromosomes I wish to concatenate
char* genome = (char*) malloc(sizeof(char) * (genome_size+chr_total));
for (int i = 0; i < chr_total; i++){
pthread_mutex_lock(&data_mutex);
const char *data = fai_fetch(seq_ref,chr_names[i],&chr_sizes[i]);
pthread_mutex_unlock(&data_mutex);
//sprintf(&genome[strlen(genome)],data);
strcat(genome,data);
//sprintf(genome+strlen(genome),data); //All three gives conditional jump or move error
//sprintf(genome,data); // THIS SOLVES VALGRIND ISSUE ONE BUT DOES NOT GIVE A CONCATENATED CHAR*
}
All of this works, but then running valgrind I get
Conditional jump or move depends on uninitialized value(s) referring to the "strcat(genome,data); "
and Uninitialized value was created by a heap allocation referring to
"char* genome = (char*) malloc(sizeof(char) * (genome_size+chr_total));"
Based on other StackOverflow answers I tried sprintf(&genome[strlen(genome)],data); and sprintf(genome+strlen(genome),data); instead of strcat. However they too gives the same valgrind message.
The only thing that seems to alleviate this error is using sprintf(genome,data); however then i will not get the full genome but just a single chromosome.
Trying genome += sprintf(genome,data); gives me ./a.out': munmap_chunk(): invalid pointer: and ./a.out': free()
In regards to the "Uninitialized value was created by a heap allocation" error -> then my issue is that I am only able to free that memory after all of the threads are done running. So I am not sure how to initialize the values in the heap allocation when I am using malloc.
Is it possible to solve some of these specific valgrind errors?
Using Valgrind to locate the problematic code
The "Conditional jump or move depends on uninitialised value(s)" message means Valgrind has determined that some result of your program depends on uninitialized memory.
Use the --track-origins=yes flag to track the origin of the uninitialized value. It might help you finding that value. From man 1 valgrind:
When set to yes, Memcheck keeps track of the origins of all uninitialised values. Then, when an uninitialised value error is reported, Memcheck will try to show the origin of the value. An origin can be one of the following four places: a heap block, a stack allocation, a client request, or miscellaneous other sources (eg, a call to brk).
More specifically in your program:
Problem 1: Using uninitialized genome
The line
char* genome = (char*) malloc(sizeof(char) * (genome_size+chr_total));
Allocates the genome buffer using malloc(2) and then consumes it in:
strcat(genome,data);
Please note that functions such as strlen(3) and strcat(3) works on C-strings, which are buffers that terminate with a null character ('\0').
malloc(2) just allocates memory and it doesn't initialize it so your allocated buffer may contain any value (and considered as uninitialized). You should avoid using string related functions with an uninitialized buffers as it results undefined behavior.
Fortunately calloc(2) does the trick - it allocates the buffer and initializes all of its bits to zero, resulting a valid 0 length C-string you can operate on. I suggest the following fix to ensure that genome is initialized:
char* genome = calloc(genome_size+chr_total+1, sizeof(char));
Also note that I've added +1 to the length of the allocated buffer. It is done to guarantee that the resulting genome will end with a null terminator (assuming that genome_size+chr_total is the total size of all the buffers returned from fai_fetch).
Also note that in terms of performance calloc is a bit slower than malloc (because it initializes the data) but for my opinion it is safer as it initializes the whole buffer. For the purposes of your specific program, you could save the performance burden by using malloc and initializing just the first byte:
char* genome = malloc(sizeof(char) * (genome_size + chr_total + 1));
if (NULL == genome) {
perror("malloc of genome failed");
exit(1);
}
// So it will be a valid 0 length c-string
genome[0] = 0;
We don't have to initialize the last byte to be 0 because strcat writes the terminating null character for us.
(Potential) Problem 2: Using potentially non-null terminated data with strcat
As you described in your question, the fai_fetch extracts some data:
const char *data = fai_fetch(seq_ref,chr_names[i],&chr_sizes[i]);
and then consumes it in the strcat line:
strcat(genome,data);
As I wrote above, because you use strcat, data should be null-terminated as well.
I'm not sure how fai_fetch is implemented but if it returns a valid C-string then you're all good.
If it doesn't then you should use strncat which works on buffers that are not null-terminated.
From man 3 strcat:
The strncat() function is similar, except that
it will use at most n bytes from src; and
src does not need to be null-terminated if it contains n or
more bytes.
I suggest the following fix:
// I'm not sure what type `&chr_sizes[i]` is, assuming it's `size_t`
size_t length = &chr_sizes[i];
const char *data = fai_fetch(seq_ref,chr_names[i], length);
// Use strcat
strncat(genome, used_data, length);
I am having an issue with a function that concatenates a number to the end of a char array. I honestly can't see the issue:
void x(int num, char* originalArray) {
char* concat_str = new char[1];
sprintf(concat_str, "%d", num);
for (int i = 0; i < 1; i++)
originalArray[i + 10] = concat_str[i];
delete [] concat_str;
}
The error message is:
HEAP CORRUPTION DETECTED: after Normal block (#147) at 0x01204CA0. CRT detected that the application wrote to the memory after the end of heap buffer.
Any ideas? I'm a beginning programmer, but I've done this same kind of thing many times and never had this issue. Thanks.
concat_str needs to be large enough to hold the number of digits in num plus a null terminator. Since it size is one you only have enough room for the null terminator. Trying to add anything else is undefined behavior as it accesses memory you do not own and causing the heap corruption.
You're allocating one byte for concat_str, and sprintf'ing something that requires more space than that.
First of all, note that your API is a C api. If you want a dynamic array in C++, use std::vector<char>.
But, assuming you need to stick to the C API, there's no way to guarantee that your originalArray is large enough to hold the result. Furthermore, the temporary buffer is unnecessary.
You should modify the API and the implementation as follows:
Take the size of the destination, to guarantee that it doesn't write past its end.
Write the string in place in the destination buffer. Putting it into a temporary buffer and then copying to the destination is a waste of time.
Use snprintf, not sprintf. The latter is not safe: you can't guarantee it won't write past the end of your buffer.
You should assert the precondition that the offset is at least smaller than the destination size.
If the precondition holds, the destination will be always properly zero-terminated, although the text representation of num might not fit in it.
You can return the length of the destination that is necessary for the value to fit.
Thus:
size_t fun(int num, char * dest, size_t dest_size) {
const size_t offset = 10;
assert(dest_size > offset);
return offset + snprintf(dest + offset, dest_size - offset, "%d", num);
}
#include <cstdio>
#include <iostream>
using namespace std;
int main ()
{
char buffer [1];
sprintf (buffer, "%d is one number", 1);
cout<<buffer<<endl;
return 0;
}
buffer's size is only one, but cout can print right result. Why?
Is it safe to do? Or I had to consider set one big size for buffer when using char * related methods?
No, it's not safe.
The C-style strings need to be null terminated, but there's not enough space in buffer. Undefined behavior doesn't mean guaranteed working or not working. When I tested your program, I got a segmentation fault.
As Yu Hao stated: It Is not safe!
But why is it working sometimes?
char buffer[1]
is not a managed array. It just gives the compiler the hint that he should reserve space for one char. the variable buffer is used as a pointer to that space and looses all information about the original size. so the above statement is the same as writing:
char bufferVar = '\0'; /* a single character */
char *buffer = &bufferVar; /* a pointer to bufferVar */
buffer just contains the address of a character but no other information at all!
your sprintf expects such an address an happy writes its string beginning at buffer.
The segmentation fault is a message from the Operating System. Your process allocates space for one byte. The OS manages your memory in pages (segments). When you cross a border of these segments a segmentation fault is raised.
As far as I know it depends on the compiler whether variable are allocated on the beginning or at the end of a segment.
Yu Hao's compiler obviously puts them at the end - yours at the front. So your sprintf doesn't write over the boundary of a segment.
Hope it helps.
As for considering the size needed to store a char * string, many of the C stdlib string functions will tell you the length they require if you pass them NULL. You can call this before allocating storage for the string to know how much storage you need:
std::cout << "You need a buffer that can store "
<< sprintf (NULL, "%d is one number", 1) + 1
<< " characters to safely store your string."
<< std::endl;
Another solution is to use something like snprintf (...), which guarantees that it will truncate the output so that it will not overrun your buffer:
snprintf (buffer, 1, "%d is one number", 1);
// ~~~
// Length of buffer
In your case, the buffer is only 1 character long so it only has enough space to store the null terminator; not particularly useful.
I have to write a function that fills a char* buffer for an assigned length with the content of a string. If the string is too long, I just have to cut it. The buffer is not allocated by me but by the user of my function. I tried something like this:
int writebuff(char* buffer, int length){
string text="123456789012345";
memcpy(buffer, text.c_str(),length);
//buffer[length]='\0';
return 1;
}
int main(){
char* buffer = new char[10];
writebuff(buffer,10);
cout << "After: "<<buffer<<endl;
}
my question is about the terminator: should it be there or not? This function is used in a much wider code and sometimes it seems I get problems with strange characters when the string needs to be cut.
Any hints on the correct procedure to follow?
A C-style string must be terminated with a zero character '\0'.
In addition you have another problem with your code - it may try to copy from beyond the end of your source string. This is classic undefined behavior. It may look like it works, until the one time that the string is allocated at the end of a heap memory block and the copy goes off into a protected area of memory and fails spectacularly. You should copy only until the minimum of the length of the buffer or the length of the string.
P.S. For completeness here's a good version of your function. Thanks to Naveen for pointing out the off-by-one error in your terminating null. I've taken the liberty of using your return value to indicate the length of the returned string, or the number of characters required if the length passed in was <= 0.
int writebuff(char* buffer, int length)
{
string text="123456789012345";
if (length <= 0)
return text.size();
if (text.size() < length)
{
memcpy(buffer, text.c_str(), text.size()+1);
return text.size();
}
memcpy(buffer, text.c_str(), length-1);
buffer[length-1]='\0';
return length-1;
}
If you want to treat the buffer as a string you should NULL terminate it. For this you need to copy length-1 characters using memcpy and set the length-1 character as \0.
it seems you are using C++ - given that, the simplest approach is (assuming that NUL termination is required by the interface spec)
int writebuff(char* buffer, int length)
{
string text = "123456789012345";
std::fill_n(buffer, length, 0); // reset the entire buffer
// use the built-in copy method from std::string, it will decide what's best.
text.copy(buffer, length);
// only over-write the last character if source is greater than length
if (length < text.size())
buffer[length-1] = 0;
return 1; // eh?
}
char * Buffers must be null terminated unless you are explicitly passing out the length with it everywhere and saying so that the buffer is not null terminated.
Whether or not you should terminate the string with a \0 depends on the specification of your writebuff function. If what you have in buffer should be a valid C-style string after calling your function, you should terminate it with a \0.
Note, though, that c_str() will terminate with a \0 for you, so you could use text.size() + 1 as the size of the source string. Also note that if length is larger than the size of the string, you will copy further than what text provides with your current code (you can use min(length - 2, text.size() + 1/*trailing \0*/) to prevent that, and set buffer[length - 1] = 0 to cap it off).
The buffer allocated in main is leaked, btw
my question is about the terminator: should it be there or not?
Yes. It should be there. Otherwise how would you later know where the string ends? And how would cout would know? It would keep printing garbage till it encounters a garbage whose value happens to be \0. Your program might even crash.
As a sidenote, your program is leaking memory. It doesn't free the memory it allocates. But since you're exiting from the main(), it doesn't matter much; after all once the program ends, all the memory would go back to the OS, whether you deallocate it or not. But its good practice in general, if you don't forget deallocating memory (or any other resource ) yourself.
I agree with Necrolis that strncpy is the way to go, but it will not get the null terminator if the string is too long. You had the right idea in putting an explicit terminator, but as written your code puts it one past the end. (This is in C, since you seemed to be doing more C than C++?)
int writebuff(char* buffer, int length){
char* text="123456789012345";
strncpy(buffer, text, length);
buffer[length-1]='\0';
return 1;
}
It should most defiantly be there*, this prevents strings that are too long for the buffer from filling it completely and causing an overflow later on when its accessed. though imo, strncpy should be used instead of memcpy, but you'll still have to null terminate it. (also your example leaks memory).
*if you're ever in doubt, go the safest route!
First, I don't know whether writerbuff should terminate the string or not. That is a design question, to be answered by the person who decided that writebuff should exist at all.
Second, taking your specific example as a whole, there are two problems. One is that you pass an unterminated string to operator<<(ostream, char*). Second is the commented-out line writes beyond the end of the indicated buffer. Both of these invoke undefined behavior.
(Third is a design flaw -- can you know that length is always less than the length of text?)
Try this:
int writebuff(char* buffer, int length){
string text="123456789012345";
memcpy(buffer, text.c_str(),length);
buffer[length-1]='\0';
return 1;
}
int main(){
char* buffer = new char[10];
writebuff(buffer,10);
cout << "After: "<<buffer<<endl;
}
In main(), you should delete the buffer you allocated with new., or allocate it statically (char buf[10]). Yes, it's only 10 bytes, and yes, it's a memory "pool," not a leak, since it's a one-time allocations, and yes, you need that memory around for the entire running time of the program. But it's still a good habit to be into.
In C/C++ the general contract with character buffers is that they be null-terminiated, so I would include it unless I had been explicitly told not to do it. And if I did, I would comment it, and maybe even use a typedef or name on the char * parameter indicating that the result is a string that is not null terminated.
I would appreciate for some C++ expertize advice on this please. I have a Char array
<unsigned char ch1[100];>
data (ASCII code) gets filled in this ( max 6 or 8 array spaces and rest is empty). I want to process valid bits in the array only either converting them to Hex or again Char array. I tried
<memcpy (ch1,ch2,sizeof(ch1))>
but all garbage values are also copied..... :(
<strcpy gives me an error>
also number of bytes copied are dynamic ( 1 time :- 4; 2 time :- 6.....)
Do you know how many valid bytes do you have in your array? If yes, you can pass that number in as the 3rd argument of memcpy.
Otherwise you can zero-initialize the array and use strcpy which will stop on the first zero:
char ch1[100];
// zero out the array so we'll know where to stop copying
memset(ch1, 0, sizeof(ch1));
... data gets filled here ....
strcpy (ch2, ch1);
// zero out array again so we'll catch the next characters that come in
memset(ch1, 0, sizeof(ch1));
... life goes on ...
So only copy the chars that are actually initialized. You as a programmer are responsible for tracking what's initialized and what's not.