I’ve read many Q&A's which seemed similar to this problem but haven’t found any answers yet:
I have to make some assignments to a dynamic byte array in the fillbyte function like this:
int Error;
result = fillbyte (&Error);
if I comment the line shown below, everything works fine. but if that line gets executed, the second time that this function is called, access violation exception will be raised however the first time the code runs properly and everything goes alright. I can’t seem to find the problem with this line of code or another way to fill the array with password bytes.
Bool fillbyte(int *Error)
{
byte BCC;
byte *Packet1 = new byte;
*Packet1 = 0x01;
*(Packet1+1) = 'P';
*(Packet1+2) = '1';
*(Packet1+3) = STX;
*(Packet1+4) = '(';
int add = sizeof(readingprops.password)*2;
for(int i=0;i<add;i++)
{
*(Packet1+(5+i)) = readingprops.password[i]; //this line raises the problem
}
*(Packet1+add+5) = ')';
*(Packet1+add+6) = ETX;
BCC = calc.CalcBCC(Packet1,add+7);
*(Packet1+add+7) = BCC;
SerialPort.Write(Packet1,add+8);
delete Packet1;
return true;
}
Any help would be appreciated
I don't see how it can ever work. You allocate one byte on the heap but treat it as multiple bytes:
byte *Packet1 = new byte;
*Packet1 = 0x01;
*(Packet1+1) = 'P'; // !!!
*(Packet1+2) = '1'; // !!!
*(Packet1+3) = STX; // !!!
*(Packet1+4) = '('; // !!!
Here you allocate just one byte
byte *Packet1 = new byte;
and then use the pointer beyond the allocated memory
*(Packet1+1) = 'P';
*(Packet1+2) = '1';
*(Packet1+3) = STX;
*(Packet1+4) = '(';
This causes undefined behaviour, sometimes it may work. So you want something like
byte Packet1 = new byte[size]
where size is appropriate for your needs (probably add + 8, since this is the amount of bytes you write to in that function). Then delete it with delete[]. You could also use stack allocation, or std::vector<byte> since this is c++.
Related
First and foremost, I'm new to cstrings and I have to use them for the assignment. I wish I didn't have to since they're a pain.
Anyway, the issue I'm having is with a function that accepts password, reverses the order, and passes it back to main. For whatever reason, I can't get it to populate the cstring tasked with holding the password. I've tried more than one way to get it working, but I've had no luck.
The function:
char* Reverse_Pass(char p_word[])
{
int last_let = strlen(p_word);
int rev_index = 0;
char* rev_pass = new char[last_let];
//cout << "\ntest 3";
rev_pass[0] = '\0';
//for (int i = last_let; i >= 0; i--)
while (p_word[last_let] != '\0')
{
rev_pass[rev_index] = p_word[last_let];
rev_index++;
last_let--;
}
return rev_pass;
}
I tried using a for loop for the process, but it throws a break point message when the result was sent to another function for verification of said password. This function at least allows the program to run without error. The issue I'm having is logical, but I can't see it.
There are a few issues here. First off is that strlen returns the length of the string not counting the null terminator. That means when you do
while (p_word[last_let] != '\0')
p_word[last_let] is '\0' since cstrign[strlen(cstring)] is the null terminator and the loop never executes. All of this though is still wrong. Really what you want to do is stop when last_let is less than 0.
This also affects rev_pass. You use
char* rev_pass = new char[last_let];
Which gives you enough storage for the string but not enough for the null terminator that all cstrings must have. What you need is
char* rev_pass = new char[last_let + 1];
Lastly, you never null terminate rev_pass. Since you know that it will be the last position that needs the null terminator you can simply use
rev_pass[last_let] = '\0';
After you allocate it.
All of those changes gives you
char* Reverse_Pass(char p_word[])
{
int last_let = strlen(p_word);
int rev_index = 0;
char* rev_pass = new char[last_let + 1];
rev_pass[last_let] = '\0';
while (last_let > 0)
{
rev_pass[rev_index++] = p_word[--last_let];
}
return rev_pass;
}
I would say three things here:
new char[last_let]; should be new char[last_let+1];, space for /0 not included in strlen returned value
rev_pass[0] = '\0'; should be `rev_pass[last_let] = '\0'; you want the string to be 0 terminated
the end loop condition is p_word[last_let] != '\0, but you are decreasing the value of last_let...so you are checking for a 0 byte before the begin of the string that is not guarantee in anyway. the strings are 0 terminated!
For the (3) I think if you flip the index usage in the loop (eg last_let for the reversed string and rev_index for the source should make the trick)
Happy coding, Ste
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
I have written this code (Uses V8 library). I went through it a couple of times and this feels like it's the only way I can write something like this. The aim of the function is to replace the JavaScript .split() function; as when using that function with a limit doesn't include the last part of the array in the returning array. EG:
var str = "Test split string with limit";
var out = str.split(' ', 2);
The array out will contain: [Test, split]. I want it to contain: [Test, split, string with limit].
I know there are pure JS ways to do this however I find them hacky and possibly slower(?) than a single C++ bind call.
Here's my function:
/**
* Explodes a string but limits the tokens
* #param input
* #param delim
* #param limit
* #return
*/
void ASEngine::Engine::ASstrtok(const v8::FunctionCallbackInfo<v8::Value>& args)
{
Assert(3, args);
Isolate* isolate = args.GetIsolate();
/* Get args */
String::Utf8Value a1(args[0]);
String::Utf8Value a2(args[1]);
Local<Uint32> a3 = args[2]->ToUint32();
std::string input = std::string(*a1);
std::string delim = std::string(*a2);
unsigned int limit = a3->Int32Value();
unsigned int inputLen = input.length();
// Declare a temporary array to shove into the return later
std::vector<char*> tmp;
tmp.reserve(limit);
unsigned int delimlen = delim.length();
char* cp = (char*) malloc(inputLen);
char* cursor = cp + inputLen; // Cursor
char* cpp = (char*) cp; // Keep the start of the string
// Copy the haystack into a modifyable char ptr
memset(cp + inputLen, 0x00, 1);
memcpy(cp, input.c_str(), inputLen);
unsigned int arrayIndex = 0;
for(unsigned int i=0;i<limit;i++)
{
if((cursor = strstr(cp, delim.c_str())) == NULL)
{
cursor = (char*) cpp + inputLen;
break;
}
for(int j=0;j<delimlen;j++)
*(cursor+j) = 0x00;
tmp.push_back(cp);
cp = cursor + delimlen;
arrayIndex++;
}
if(*(cp) != '\0')
{
arrayIndex++;
tmp.push_back(cp);
}
Handle<Array> rtn = Array::New(args.GetIsolate(), arrayIndex);
/* Loop through the temporary array and assign
the variables to the V8 array */
for(unsigned int i=0;i<arrayIndex;i++)
{
rtn->Set(i, String::NewFromUtf8(
isolate, tmp[i], String::kNormalString, strlen(tmp[i])
));
}
/* Clean up memory */
delete cpp;
cp = NULL;
cpp = NULL;
cursor = NULL;
isolate = NULL;
/* Set the return */
args.GetReturnValue().Set(rtn);
}
If you are wondering: The variable cpp is there so I can delete the character pointer after I am done (As calling v8's String::NewFromUtf8() function copies the string) and I modify the cp pointer during the process of the function.
Before optimising, I would fix the code so that it is correct.
char* cp = (char*) malloc(inputLen);
...
/* Clean up memory */
delete cpp;
Whilst in some implementations, new and malloc do exactly the same thing, other implementations do not. So, if you allocate with malloc, use free to free the memory, not delete.
If you want to be clever about it, I expect:
tmp.reserve(limit+1);
will ensure that you have space for the remainder of the string without further allocation in the vector.
Since cursor isn't used after the loop, setting it inside the if that breaks the loop makes no sense.
if((cursor = strstr(cp, delim.c_str())) == NULL)
{
cursor = (char*) cpp + inputLen;
break;
}
You are using casts to (char *) in places that don't need it, for example:
char* cpp = (char*) cp; // Keep the start of the string
(cp is a char * already).
This:
memset(cp + inputLen, 0x00, 1);
is the same as:
cp[inputlen] = 0;
but unless the compiler inlines the memset, much faster.
Likewsie:
*(cursor+j) = 0x00;
can be written:
cursor[j] = 0;
However, assuming delimLen is greater than 1, you could get away with:
for(int j=0;j<delimlen;j++)
*(cursor+j) = 0x00;
converted to:
*cursor = 0;
Since your new cp value will skip to beyond delimlen anyway.
These serve absolutely no purpose:
cp = NULL;
cpp = NULL;
cursor = NULL;
isolate = NULL;
Unfortunately, I expect most of the time in your function won't be in any of the code I've commented on. But in the passing arguments back and forth between the calling JS library and the native C++ code. I'd be surprised if you gain anything over writing the same code in JS. (None of the above make much of a difference when it comes to speed, it's just correctness and "a small number of potentially wasted cycles if the compiler is rather daft").
#include <iostream>
using namespace std;
struct my_chunk
{
int size;
char* data;
};
my_chunk* make_chunk()
{
my_chunk* new_chunk = new my_chunk;
new_chunk->size = 32;
new_chunk->data = new char[32];
new_chunk->data[0] = 'h';
new_chunk->data[1] = 'e';
new_chunk->data[2] = 'l';
new_chunk->data[3] = 'l';
new_chunk->data[4] = 'o';
new_chunk->data[5] = '5';
new_chunk->data[5] = 'h';
new_chunk->data[6] = 'e';
new_chunk->data[7] = 'l';
new_chunk->data[8] = 'l';
new_chunk->data[9] = 'o';
new_chunk->data[10] = 'h';
new_chunk->data[11] = 'e';
new_chunk->data[12] = 'l';
new_chunk->data[13] = 'l';
new_chunk->data[14] = 'o';
new_chunk->data[15] = 'h';
new_chunk->data[16] = 'e';
new_chunk->data[17] = 'l';
new_chunk->data[18] = 'l';
new_chunk->data[19] = 'o';
new_chunk->data[20] = 'h';
new_chunk->data[21] = 'e';
new_chunk->data[22] = 'l';
new_chunk->data[23] = 'l';
new_chunk->data[24] = 'o';
new_chunk->data[25] = 'h';
new_chunk->data[26] = 'e';
new_chunk->data[27] = 'l';
new_chunk->data[28] = 'l';
new_chunk->data[29] = 'h';
new_chunk->data[30] = 'e';
new_chunk->data[31] = 'l';
return new_chunk;
}
void main()
{
my_chunk* same_chunk;
same_chunk = make_chunk();
std::cout << same_chunk->data;
std::cout << std::endl;
system("pause");
}
That is the simple code I compile. No matter the size I size my char* data to it adds some form of padding. It does not appear to be an alignment issue, perhaps I am wrong on that point however.
What I know is that when I size my char* data = new char[size] I can easily access beyond element [size]. The fact I can access beyond and set those elements suggests to me a massive problem has occurred.
For clarification that means in my code above, I could add a line that goes new_chunk->data[38] = 'x' without any error, crash, or anything. I have tested it, it works fine.
This isn't a huge issue, as I am given enough memory to fit my data. The only problem is that I don't understand why this is happening, and would prefer to fix it.
Also this is the output of my Program:
hellohellohellohellohellohellhel²²²²½½½½½½½½¯■¯■
Press any key to continue . . .
Edit:
This has exploded with helpful insights, perhaps I can get one more bit of help related to all this.
Why does Visual Studio 2013 show the char* beyond its length? It shows the "hellohellohellohellohellohellhel²²²²½½½½½½½½¯■¯■" which was suggesting to me that it was allocating too much memory. As a side note, the output is always the same (so far). This is when I debug, looking at the variables it shows exactly what is output.
char* need a trailing '\0' to be printed properly by std::cout. So this line std::cout << same_chunk->data; will iterate in memory till it find a zero...
That can cause a crash, printing garbage, ...
By the way there is no bound checking for pointer access in C++ so whenever you write data[X] the program try to go to adresse of data + X time the size of one data element (here char).
If you want bound access (and you want it) use either a std::string (neat for characters) or a std::vector (neat for anything).
Here's another perspective based on a lower-level view:
When you call new (or malloc), the library (libc?) will request some memory from the OS. This memory is most likely in page form (ie. 4K, 2M, etc bytes large). Depending on the algorithm that the library uses to manage dynamic memory, a couple of things can happen:
Your data[] pointer happens to be right at the back edge of this page, and you get a page fault (program crash, expected behaviour)
More likely, the library allocated you some space in the middle of a page. Since C++ doesn't do bounds checking (as answered by others), it treats this data* pointer as a pointer to a list of bytes in memory. Since the granularity of the space allocated to the heap is rather large, you can be accessing mapped pages (ie. no program crash), that have rubbish values (ie. uninitialised values).
Also, another thing to note is that when you request a block of memory 32 bytes long, nothing dictates you get one that is exactly 32 bytes long. new[] might give you a region 1024 bytes long, or 400000 bytes long. The only guarantee is that it is at least 32 bytes long. Therefore, this is another reason (although not the main reason) that your program doesn't crash.
C++ doesn't really check to make sure an array index is within the initial chunk of memory allocated for the array. When you are accessing the "extra" memory, you're basically just accessing some unrelated memory and casting it as a character. It isn't ALLOCATED as part of the array, just ACCESSIBLE as if it were. And assigning values to those random memory locations is just overwriting memory randomly... Bad idea.
C and C++ do not do bounds checking. So basically you just got lucky that you didn't get a segfault when you accessed a location past the bounds of your allocated memory.
the [38] notation basically says move to the equivalent address of data + 38 * sizeof(char *). So if this space were to be marked as poison, you woulda been out of luck.
I want to successfully allocate an Array in my Memory Manager. I am having a hard time getting the data setup successfully in my Heap. I don't know how to instantiate the elements of the array, and then set the pointer that is passed in to that Array. Any help would be greatly appreciated. =)
Basically to sum it up, I want to write my own new[#] function using my own Heap block instead of the normal heap. Don't even want to think about what would be required for a dynamic array. o.O
// Parameter 1: Pointer that you want to pointer to the Array.
// Parameter 2: Amount of Array Elements requested.
// Return: true if Allocation was successful, false if it failed.
template <typename T>
bool AllocateArray(T*& data, unsigned int count)
{
if((m_Heap.m_Pool == nullptr) || count <= 0)
return false;
unsigned int allocSize = sizeof(T)*count;
// If we have an array, pad an extra 16 bytes so that it will start the data on a 16 byte boundary and have room to store
// the number of items allocated within this pad space, and the size of the original data type so in a delete call we can move
// the pointer by the appropriate size and call a destructor(potentially a base class destructor) on each element in the array
allocSize += 16;
unsigned int* mem = (unsigned int*)(m_Heap.Allocate(allocSize));
if(!mem)
{
return false;
}
mem[2] = count;
mem[3] = sizeof(T);
T* iter = (T*)(&(mem[4]));
data = iter;
iter++;
for(unsigned int i = 0; i < count; ++i,++iter)
{
// I have tried a bunch of stuff, not sure what to do. :(
}
return true;
}
Heap Allocate function:
void* Heap::Allocate(unsigned int allocSize)
{
Header* HeadPtr = FindBlock(allocSize);
Footer* FootPtr = (Footer*)HeadPtr;
FootPtr = (Footer*)((char*)FootPtr + (HeadPtr->size + sizeof(Header)));
// Right Split Free Memory if there is enough to make another block.
if((HeadPtr->size - allocSize) >= MINBLOCKSIZE)
{
// Create the Header for the Allocated Block and Update it's Footer
Header* NewHead = (Header*)FootPtr;
NewHead = (Header*)((char*)NewHead - (allocSize + sizeof(Header)));
NewHead->size = allocSize;
NewHead->next = NewHead;
NewHead->prev = NewHead;
FootPtr->size = NewHead->size;
// Create the Footer for the remaining Free Block and update it's size
Footer* NewFoot = (Footer*)NewHead;
NewFoot = (Footer*)((char*)NewFoot - sizeof(Footer));
HeadPtr->size -= (allocSize + HEADANDFOOTSIZE);
NewFoot->size = HeadPtr->size;
// Turn new Header and Old Footer High Bits On
(NewHead->size |= (1 << 31));
(FootPtr->size |= (1 << 31));
// Return actual allocated memory's location
void* MemAddress = NewHead;
MemAddress = ((char*)MemAddress + sizeof(Header));
m_PoolSizeTotal = HeadPtr->size;
return MemAddress;
}
else
{
// Updating descriptors
HeadPtr->prev->next = HeadPtr->next;
HeadPtr->next->prev = HeadPtr->prev;
HeadPtr->next = NULL;
HeadPtr->prev = NULL;
// Turning Header and Footer High Bits On
(HeadPtr->size |= (1 << 31));
(FootPtr->size |= (1 << 31));
// Return actual allocated memory's location
void* MemAddress = HeadPtr;
MemAddress = ((char*)MemAddress + sizeof(Header));
m_PoolSizeTotal = HeadPtr->size;
return MemAddress;
}
}
Main.cpp
int* TestArray;
MemoryManager::GetInstance()->CreateHeap(1); // Allocates 1MB
MemoryManager::GetInstance()->AllocateArray(TestArray, 3);
MemoryManager::GetInstance()->DeallocateArray(TestArray);
MemoryManager::GetInstance()->DestroyHeap();
As far as these two specific points:
Instantiate the elements of the array
Set the pointer that is passed in to that Array.
For (1): there is no definitive notion of "initializing" the elements of the array in C++. There are at least two reasonable behaviors, this depends on the semantics you want. The first is to simply zero the array (see memset). The other would be to call the default constructor for each element of the array -- I would not recommend this option as the default (zero argument) constructor may not exist.
EDIT: Example initialization using inplace-new
for (i = 0; i < len; i++)
new (&arr[i]) T();
For (2): It is not exactly clear what you mean by "and then set the pointer that is passed in to that Array." You could "set" the memory returned as data = static_cast<T*>(&mem[4]), which you already do.
A few other words of cautioning (having written my own memory managers), be very careful about byte alignment (reinterpret_cast(mem) % 16); you'll want to ensure you are returning points that are word (or even 16 byte) aligned. Also, I would recommend using inttypes.h to explicitly use uint64_t to be explicit about sizing -- current it looks like this allocator will break for >4GB allocations.
EDIT:
Speaking from experiment -- writing a memory allocator is a very difficult thing to do, and it is even more painful to debug. As commenters have stated, a memory allocator is specific to the kernel -- so information about your platform would be very helpful.
I'm resizing an array. The resize (doubling the size) appears to work correctly, but when I send more text into the resized array, when it reaches what would have been the limit of the array before it was resized, I get a "Debug Assertion Failed! Expression: (L"Buffer is too small" && 0)" error. I've tried it a few different ways, always with the same result.
static int ReadBufferSize, totalChars;
static char *ReadBuffer = NULL;
ReadBuffer = (char *)malloc(ReadBufferSize);
...
//Double buffer size.
if((float)totalChars > (0.75f) * (float)ReadBufferSize)
{
char *tempBuffer = NULL;
tempBuffer = (char *)malloc(2 * ReadBufferSize);
if(tempBuffer == NULL)
free(tempBuffer);
else
{
memcpy(tempBuffer,ReadBuffer,strlen(ReadBuffer)+1);
free(ReadBuffer);
ReadBuffer = tempBuffer;
tempBuffer = NULL;
ReadBufferSize *= 2;
}
}
For my testing, ReadBufferSize has been set initially to 85 characters. After the code resizing the array is executed, the text in ReadBuffer is still displayed on the screen. I type more characters and they are sent into the array, and from there, displayed on the screen. But when the number of characters reaches 85 characters, I get the "Debug Assertion Failed! Expression: (L"Buffer is too small" && 0)" error, when there should now be space for 170 characters. I've also tried the following.
//Double buffer size.
if((float)totalChars > (0.75f) * (float)ReadBufferSize)
{
char* temp = 0;
temp = new char[2 * ReadBufferSize];
for(unsigned int i = 0; i < strlen(ReadBuffer); i++)
temp[i] = ReadBuffer[i];
temp[strlen(ReadBuffer)] = '\0';
delete[] ReadBuffer;
ReadBuffer = temp;
temp = 0;
ReadBufferSize *= 2;
}
I've also tried:
malloc(2 * ReadBufferSize * sizeof(char));
and:
strcpy_s(tempBuffer, strlen(ReadBuffer)+1, ReadBuffer);
Many thanks.
Since you didn't provided the full minimal program it's difficult to say what is wrong.
You should normally start your program in the debugger, put breakpoint inside your function and reproduce the problem. Take a look at all variables and functions like strlen(). They might return values that you don't expect.
Offtopic, but for real applications you should better use std::string which does all the tricks with memory management automatically.
I figured it out. I was about to post some more of my code to give you more information when I noticed the problem. I had a "pageSize" variable that I had been using for the size of the array. Then when I wanted to start dynamically changing the size, I separated the array size from the page size by creating the "ReadBufferSize" variable. Unfortunately, I still had "pageSize" in the segment of code where I was putting characters into the array:
strcat_s(ReadBuffer, pageSize, keystroke);
I've now changed it to
strcat_s(ReadBuffer, ReadBufferSize, keystroke);
and everything seems to be working. Thanks to everyone for taking the time to look at this. I was fixated on the idea that the problem must be in the section of code for resizing the array, not elsewhere.