I allocate some memory with malloc - about 128 bytes.
Later on, I call realloc with about 200 bytes, but it's returning null!
It returns a valid pointer if I do free, and then another malloc, however I would like to use realloc.
What could explain this behavior (I clearly am not running out of memory)? Is this valid behavior?
Code bits:
//class constructor
size = 0;
sizeAllocated = DEFAULT_BUFFER_SIZE; //64
data = (char*)malloc(sizeAllocated * sizeof(char)); //data is valid ptr now, I've checked it
data[0] = '\0';
//later on:
//append function
bool append(char** data, const char* str, size_t strLen) {
if((size + strLen) >= sizeAllocated) {
sizeAllocated += strLen + 1 + BUFFER_ALLOCATION_STEP;
char* temp = realloc(*data, sizeAllocated * sizeof(char));
if(temp)
*data = temp;
return( temp != NULL );
}
EDIT: fixed. I was overloading the << operator for my class, and had it return *this instead of void. Somehow this was screwing everything up! If anyone could explain why this happen, it would be nice!
Since the following comment was added to the question
data = (char*)realloc(data, (size_t)(sizeAllocated * sizeof(char)));
if I replace sizeAllocated with a
constant that is same value, it
reallocs correctly
Now we can figure out what happened. You replaced sizeAllocated with a constant that DID NOT have the same value. For debugging purposes, add a statement that will output the value of sizeAllocated and you will be surprised.
Related
I've still getting an error of how the stack around newRow is tried using strncat() so that I can say how many new charters that where added to the string, but in the end I still have a corruption around newRow.
In terms of a variables being passed into this function, I think they are pretty straight forward. I also use sizeOfString as a custom made function because I'm not allowed to use the standard sizeof function.
char* makeRow(char elementOne[20], int elementNumber, int numCycles, int orginalData[40], float ctValues[7]){
char newRow[] = "";
int lookingAt;
int dataPoint;
char* elementPtr;
int charArrSize;
elementNumber = elementNumber--;
elementPtr = elementOne;
int lenOfElemnt = *(&elementOne + 1) - elementOne;
//charArrSize = sizeOfString(elementPtr);
charArrSize = sizeOfString(elementOne);
strncat(newRow, elementOne, charArrSize);
//strcpy(csvThirdRow, (",%s", elementOne));
for (int i = 1; i <= 5; i++)
{
lookingAt = (((i - 1) * 5) + 1 - 1);
int maxLookingAt = numCycles * 5;
dataPoint = orginalData[lookingAt];
char dataPointBuffer[100];
if (lookingAt < maxLookingAt)
{
sprintf(dataPointBuffer, ",%d", dataPoint);
charArrSize = sizeOfString(dataPointBuffer);
strncat(newRow, dataPointBuffer, charArrSize);
}
else
{
strncat(newRow, ",",1);
}
}
char ctBuffer[20];
float ctNumber = ctValues[elementNumber];
sprintf(ctBuffer, ",%.2f\n", ctNumber);
charArrSize = sizeOfString(ctBuffer);
strncat(newRow, ctBuffer, charArrSize);
return newRow;
}
If we omit the array dimension, compiler computes it for us based on the size of initialiser.
So, this
char newRow[] = "";
is same as this
char newRow[1] = "";
The size of newRow array is 1.
You are trying to copy more than 1 character to newRow array which is leading to undefined behaviour and resulting in corruption.
From strncat():
The behavior is undefined if the destination array does not have enough space for the contents of both dest and the first count characters of src, plus the terminating null character....
May you should try giving enough size to newRow array, like this
char newRow[1024] = {0};
There is another problem in your code -
You are returning the address of local variable newRow1) from makeRow() function. Note that a local(automatic) non-static variable lifetime is limited to its scope i.e. the block in which it has been declared. Any attempt to access it outside of its lifetime lead to undefined behaviour.
Couple of things that you can do to fix it:
Either make numRow array static or declare numRow as char * type and allocate memory dynamically to it and, in this case, make sure to free it once done with it.
1). An expression that has type array of type is converted to an expression with type pointer to type that points to the initial element of the array object [there are few exceptions to this rule].
I'm getting an error in the following code. Visual Studio throws an access violation error when writing to _buf. How can I fix this?
The Sendn function is a socket sending function. It's not the problem, you can ignore it.
It looks like _buf points at 0x00000000
The error message I'm seeing is
0xC0000005: 0x00000000 : access violation
void ?????::?????(int number, string title)
{
int titlesize = sizeof(title);
int bufsize = 4 + 4 + 4 + titlesize;
char *_buf = new char[bufsize];
_buf = { 0 };
// char _buf[bufsize] = { 0 }; (수정 내용)
int commands = 3;
int index = 0;
memcpy(_buf, &commands, sizeof(int));
index += sizeof(int);
memcpy(_buf + index, &number, sizeof(int));
index += sizeof(int);
memcpy(_buf + index, &titlesize, sizeof(int));
index += sizeof(int);
for (int i = 0; i < titlesize; i++)
{
memcpy(_buf + index, &title[i], sizeof(char));
index += sizeof(char);
}
Sendn(_buf, bufsize);
delete[] _buf;
return;
}
char *_buf = new char[bufsize];
_buf = { 0 };
This does not zero-fill the dynamically-allocated array pointed to by _buf. It sets the pointer _buf to be a null pointer. Since _buf is a null pointer, later attempts to dereference it lead to undefined behavior.
There's no need to zero-fill the array pointed to by _buf in this case, so you can simply remove the _buf = { 0 }; line.
Once you've fixed that problem, you also aren't allocating the right amount of memory. sizeof(title) will not give you the number of characters that title holds. It just gives you the static size of a std::string object, which is usually only a pointer and two integers. Use title.size() instead.
You're trying to copy the content of title together with 3 other integer numbers into _buf right? The problem is that sizeof(title) is not the length of the string stored in title. In order to get the length of title, you need to call the member function length on type std::string like this:
auto titlesize = title.length();
The sizeof operator only gives you the size of your std::string object on stack (in comparison, the actual string is stored on heap) and sizeof expressions are always constant expressions. On my computer, sizeof(std::string) is 24 regardless of what the actual string is.
I am currently working on an Arduino platform and I am trying to get rid of all Strings through char [] and pointers in order to avoid problems with the memory of my Arduino nano. The following code was being used to generate a string and pass to a function which expects a char *:
char * ptr = "";
strcpy(ptr, "AT+CWJAP=\"");
strcat(ptr, wifi_ssid);
strcat(ptr,"\",\"");
strcat(ptr,WIFI_PASS);
strcat(ptr,"\"");
Serial.println(ptr);
addToPipe(ptr);
where:
void ESP8266::addToPipe(char * cmd) {
for(pipeSlot = 0; pipeSlot < PIPEMAXSIZE; pipeSlot++) {
if(isCharArrayEmpty(pipe[pipeSlot])){
Serial.print("Slot is Empty. New data:");
Serial.println(cmd);
pipe[pipeSlot] = cmd;
pipeSlot = PIPEMAXSIZE; //for breaking loop
} else {
Serial.print("Slot is Full with:");
Serial.println(pipe[pipeSlot]);
}
}
printPipe();
}
but for some non-apparent reason the pointer ptr was being printed in the Serial port continuously. However, by changing the above string generation with the following:
char * ptr = malloc(1);
strcpy(ptr, "AT+CWJAP=\"");
strcat(ptr, wifi_ssid);
strcat(ptr,"\",\"");
strcat(ptr,WIFI_PASS);
strcat(ptr,"\"");
Serial.println(ptr);
addToPipe(ptr);
seems to get rid of the problem. The question is, what is the difference between:
1. char * ptr = "";
2. char * ptr = malloc(1);
3. char * ptr = NULL
Thanks in advance
When you do this:
char * ptr = malloc(1);
You're only allocating enough space for a single byte. When you then try to strcat or strcpy anything to it, you're writing past the bounds of allocated memory. This invokes undefined behavior.
Assigning "" to ptr also won't work because it now points to a (empty) string literal and string literals can't be modified. Assigning NULL also won't work because it's undefined behavior to dereference a NULL pointer.
You need to allocate enough space to hold the entire string plus the terminating null byte:
char *ptr = malloc(10 + strlen(wifi_ssid) + 3 + strlen(WIFI_PASS) + 1 + 1);
strcpy(ptr, "AT+CWJAP=\"");
strcat(ptr, wifi_ssid);
strcat(ptr,"\",\"");
strcat(ptr,WIFI_PASS);
strcat(ptr,"\"");
Considering the following code block:
Byte* b = (Byte*) var.rawBuffer();
b += sizeof (Byte) * 9;
WhateverType* aptr = (WhateverType*) b;
WhateverType* anotherptr = aptr;
for (int i = 0; i < N; i++) {
assert(*anotherptr == aptr[i]);
anotherptr += sizeof (WhateverType);
}
Why do the assertion fail, sometimes? Is not scanning allocated memory using the [] operator with an index on the starting memory address equivalent to increment the pointer address by the size of the data type I am trying to read?
The problem is this line:
anotherptr += sizeof (WhateverType);
anotherptr is a WhateverType* pointer, not a Byte* pointer. When you perform arithmetic on a typed pointer, the total byte count is an even multiple of the type that the pointer is declared as.
So, in the line above, you are not telling the compiler to increment the pointer by just sizeof (WhateverType) number of bytes only, like you are expecting. You are actually telling it to increment the pointer by sizeof(WhateverType) number of elements, or in other words, by sizeof(WhateverType) * sizeof(WhateverType) number of bytes.
T *pointer = ...;
pointer += N;
Is effectively equivalent to the following:
pointer = reinterpret_cast<T*>(reinterpret_cast<byte*>(pointer) + (sizeof(T) * N));
Even the statement aptr[i] works the same way, as the expression pointer[N] is just syntax sugar for *(pointer + N).
For what you are attempting, you need to increment your anotherptr pointer by N=1 element, not by N=sizeof(WhateverType) number of elements. So, use this instead:
anotherptr += 1;
Or simpler:
anotherptr++; // or: ++anotherptr;
I have attached my code below. I do not see what I am doing wrong. I have a struct that I am trying to serialize into a byte array. I have wrote some some simple code to test it. It all appears to work during runtime when I print out the values of objects, but once I hit return 0 it throws the error:
Run-Time Check Failure #2 - Stack around the variable 'command' was corrupted.
I do not see the issue. I appreciate all help.
namespace CommIO
{
enum Direction {READ, WRITE};
struct CommCommand
{
int command;
Direction dir;
int rwSize;
BYTE* wData;
CommCommand(BYTE* bytes)
{
int offset = 0;
int intsize = sizeof(int);
command = 0;
dir = READ;
rwSize = 0;
memcpy(&command, bytes + offset, intsize);
offset += intsize;
memcpy(&dir, bytes + offset, intsize);
offset += intsize;
memcpy(&rwSize, bytes + offset, intsize);
offset += intsize;
wData = new BYTE[rwSize];
if (dir == WRITE)
{
memcpy(&wData, bytes + offset, rwSize);
}
}
CommCommand() {}
}
int main()
{
CommIO::CommCommand command;
command.command = 0x6AEA6BEB;
command.dir = CommIO::WRITE;
command.rwSize = 128;
command.wData = new BYTE[command.rwSize];
for (int i = 0; i < command.rwSize; i++)
{
command.wData[i] = i;
}
command.print();
CommIO::CommCommand command2(reinterpret_cast<BYTE*>(&command));
command2.print();
cin.get();
return 0;
}
The following points mentioned in comments are most likely the causes of your problem.
You seem to be assuming that the size of Direction is the same as the size of an int. That may indeed be the case, but C++ does not guarantee it.
You also seem to be assuming that the members of CommIO::CommCommand will be laid out in memory without any padding between, which again may happen to be the case, but is not guaranteed.
There are couple of ways to fix the that.
Make sure that you fill up the BYTE array in the calling function with matching objects, or
Simply cast the BYTE* to CommCommand* and access the members directly.
For (1), you can use:
int command = 0x6AEA6BEB;
int dir = CommIO::WRITE;
int rwSize = 128;
totatlSize = rwSize + 3*sizeof(int);
BYTE* data = new BYTE[totalSize];
int offset = 0;
memcpy(data + offset, &comand, sizeof(int));
offset += sizeof(int);
memcpy(data + offset, &dir, sizeof(int));
offset += sizeof(int);
memcpy(data + offset, &rwSize, sizeof(int));
offset += sizeof(int);
for (int i = 0; i < rwSize; i++)
{
data[i + offset] = i;
}
CommIO::CommCommand command2(data);
For (2), you can use:
CommCommand(BYTE* bytes)
{
CommCommand* in = reinterpret_cast<CommCommand*>(bytes);
command = in->command;
dir = in->dir;
rwSize = in->size;
wData = new BYTE[rwSize];
if (dir == WRITE)
{
memcpy(wData, in->wData, rwSize);
}
}
The other error is that you are using
memcpy(&wData, bytes + offset, rwSize);
That is incorrect since you are treating the address of the variable as though it can hold the data. It cannot.
You need to use:
memcpy(wData, bytes + offset, rwSize);
The memory for your struct is laid out without padding, this can be rectified by adding the macro #pragma pack(1) at the start of the struct and #pragma pop() at the end of the struct - check its syntax though.
For your struct to byte conversion, I would use something simple as:
template<typename T, typename IteratorForBytes>
void ConvertToBytes(const T& t, IteratorForBytes bytes, std::size_t pos = 0)
{
std::advance(bytes, pos);
const std::size_t length = sizeof(t);
const uint8_t* temp = reinterpret_cast<const uint8_t*>(&t);
for (std::size_t i = 0; i < length; ++i)
{
(*bytes) = (*temp);
++temp;
++bytes;
}
}
Where T is the is the struct in your case your Command struct and bytes would be the array.
CommIO::CommCommand command;
command.wData = new BYTE[command.rwSize];
ConvertToBytes(command, command.wData);
The resulting array would contain the expected bytes You could specify the offset as well as an extra parameter if you want to start filling your byte array from a particular location
The main problem is here:
memcpy(&wData, bytes + offset, rwSize);
Member wData is a BYTE *, and you seem to mean to copy bytes into the space to which it points. Instead, you are copying data into the memory where the pointer value itself is stored. Therefore, if you copy more bytes than the size of the pointer then you will overrun its bounds and produce undefined behavior. In any case, you are trashing the original pointer value. You probably want this, instead:
memcpy(wData, bytes + offset, rwSize);
Additionally, although the rest of the deserialization code may be right for your actual serialization format, it is not safe to assume that it is right for the byte sequence you present to it in your test program via
CommIO::CommCommand command2(reinterpret_cast<BYTE*>(&command));
As detailed in comments, you are making assumptions about the layout in memory of a CommIO::CommCommand that C++ does not guarantee will hold.
At
memcpy(&wData, bytes + offset, rwSize);
you copy from the location of the wData pointer and to the location of the wData pointer of the new CommCommand. But you want to copy from and to the location that the pointer points to. You need to dereference. You corrupt the heap, because you have only sizeof(BYTE*) space (plus some extra, because heap blocks cannot be arbitrarily small), but you copy rwSize bytes, which is 128 bytes. What you probably meant to write is:
memcpy(wData, *(BYTE*)(bytes + offset), rwSize);
which would take use the pointer stored at bytes + offset, rather than the value of bytes + offset itself.
You also assume that your struct is tightly packed. However, C++ does not guarantee that. Is there a reason why you do not override the default copy constructor rather than write this function?