I'm writing a code for calculate AES by CUDA but I have some problems with realloc() on the CPU side of the code.
When I read the data from the disk I need to encrypt I use this piece of code:
puint4 * cipher_block;
u32 posizione = 0;
FILE * inputFile = fopen("input.in","rb");
while(!feof(inputFile)){
if((cipher_block = (puint4 *)realloc(cipher_block,sizeof(puint4)*(posizione+1))) == NULL){
printf("\nERROR\n");
}
//read data
.....
posizione++;
}//end while
It works fine until I add (following) another piece of code which I use for allocate the memory on the GPU:
puint4 * round_key_GPU;
puint4 * cipher_block_GPU;
cudaMalloc((void**)&round_key_GPU,sizeof(puint4)*11);
cudaMalloc((void**)&cipher_block_GPU,sizeof(puint4)*(posizione+1));
//other instructions
....
/* Libero le risorse */
cudaFree(round_key_GPU);
cudaFree(cipher_block_GPU);
free(round_key_GPU);
free(cipher_block_GPU);
free(cipher_block);
free(round_key);
When I add this piece of code the realloc() instruction returns the error:
*** Error in `./test.x': realloc(): invalid pointer: 0x0000000000402338 ***
And if I delete
free(round_key_GPU);
free(cipher_block_GPU);
It return the error:
test.x: malloc.c:2842: mremap_chunk: Assertion `((size + offset) & (_rtld_global_ro._dl_pagesize - 1)) == 0' failed.
So I think that maybe the round_key_GPU and cipher_block_GPU pointer have been allocated before the while loop finish to read all the data and then the realloc() overwrite the memory space of the pointers. What do you think? If is this the case how can i read the data from the disk without know how much data i have to read?
(P.S. puint4 is a typedef structure with 4 unsigned int, like uint4)
Thank!
Davide
Related
I was trying to understand underlying process when pointers, strings and functions are combined along with heap/stack memory. I was able to understand and learn, but I ended up with two errors which I failed to find out why.
My problem lies here:
// printf("%s\n", *ptrToString); // Gives bad mem access error if heap memory used
// printf("%s\n", ptrToString); // Output is wrong if stack was used for memory, and prints some hex values instead
Can anyone explain what am I missing here ? Also, I would like to ask some feedback about my code, and suggest any improvements we can make.
Thanks
Full code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define USE_STACK_MEMORY 0
char* NewString(char string[])
{
unsigned long num_chars;
char *copy = NULL;
// Find string length
num_chars = strlen(string);
// Allocate memory
#if USE_STACK_MEMORY
copy = alloca(sizeof(copy) + num_chars + 1); // Use stack memory
#else
copy = malloc(sizeof(copy) + num_chars + 1); // Use heap memory
#endif
// Make a local copy
strcpy(copy, string);
// If we use stack then it returns a string literal
return copy;
}
int main(void)
{
char *ptrToString = NULL;
ptrToString = NewString("HI");
printf("%s\n", ptrToString);
// printf("%s\n", *ptrToString); // Gives bad mem access error if heap memory used
// printf("%s\n", ptrToString); // Output is wrong if stack was used for memory, and prints some hex values instead
#if !USE_STACK_MEMORY
if ( ptrToString ) {
free(ptrToString);
}
#endif
return 0;
}
The first print reads the value where the pointer points to. It interprets this value then as a pointer to a string. This means the first value of your string will be interpreted as the address where the string would be.
The second print is wrong for stack memory because the memory you allocate with alloca is automatically freed as soon as your NewString method returns.
From the man page of alloca:
The alloca() function allocates size bytes of space in the stack frame
of the caller. This temporary space is automatically freed when the
function that called alloca() returns to its caller.
I am trying using the arduino IDE to write a sketch. I have data in progmem and want to move the data with a function to a memory address allocated using malloc. My code is below:
const uint8_t Data_6 [256] PROGMEM = { 0x11, 0x39......};
void setup() {
Serial.begin(57600);
oddBallData (Data_6, 0x00, 256);
}
void main() {
}
void oddBallData(const uint8_t *data, uint8_t mem, uint16_t bytes) {
uint8_t *buff1 = (uint8_t*)malloc(sizeof(bytes));
if (buff1 = 0) {
Serial.println(F("FATAL ERROR - NO MEMORY"));
}
else {
for (uint16_t x = 0; x < 6; x++ ) {
buff1[x] = data[x]; //edited from data[0] to [x] made a mistake in post
Serial.println(buff1[x],HEX);
}
}
buff1[0] = data[0];
Serial.println(buff1[0],HEX);
free(buff1);
}
I have some data saved in progmem and want to write that data to a second device using i2c protocol. I have multiple constant arrays of data saved to my progmem, with different sizes. So I have used malloc to reserve some memory from the heap, inside of the function.
I have not been able to write the data from the progmem so I have stripped things back to so that I am just trying to point to the progmem data using malloc and then print it.
This is where I found a the problem. If I print a single array entry from the data constant. It prints the correct value. If I use a loop I get mixed results, the loop works as long as the condition check value is below 3 or sometimes below 6!!!...?
If above this value the entire print is just garbage. Can anyone explain what I am seeing?
The culprit is probably
uint8_t *buff1 = (uint8_t*)malloc(sizeof(bytes));
sizeof(bytes) returns the size of the variable (which is probably 2 bytes) so you are just allocating 2 bytes of memory. You should use the value directly, eg:
uint8_t* buff1 = malloc(bytes);
Mind that the cast is not required in C since a void* is convertible to any other pointer type directly.
Again - AVR PROGMEM is not directly accessible from memory space, it needs different instruction than access into the RAM. If you are using it like this, you'll get RAM content on passed address, not the FLASH one. You have to use special functions for this. For example memcpy_P(ram_buff,flash_ptr); makes a copy from flash into the ram. Or you can read one byte by pgm_read_byte(flash_ptr + offset)
BTW: If you are using Data_6[0] and it's working, it's just because compiler sees it as a constant and constant can be replaced by its value compile time.
I Guess you just forgot to flush()
try to do Serial.flushI() after Serial.println(buff1[x],HEX);
you can also check flush documentation
Sorry for the post. I have researched this but..... still no joy in getting this to work. There are two parts to the question too. Please ignore the code TWI Reg code as its application specific I need help on nuts and bolts C problem.
So... to reduce memory usage for a project I have started to write my own TWI (wire.h lib) for ATMEL328p. Its not been put into a lib yet as '1' I have no idea how to do that yet... will get to that later and '2'its a work in progress which keeps getting added to.
The problem I'm having is with reading multiple bytes.
Problem 1
I have a function that I need to return an Array
byte *i2cBuff1[16];
void setup () {
i2cBuff1 = i2cReadBytes(mpuAdd, 0x6F, 16);
}
/////////////////////READ BYTES////////////////////
byte* i2cReadBytes(byte i2cAdd, byte i2cReg, byte i2cNumBytes) {
static byte result[i2cNumBytes];
for (byte i = 0; i < i2cNumBytes; i ++) {
result[i] += i2cAdd + i2cReg;
}
return result;
}
What I understand :o ) is I have declared a Static byte array in the function which I point to as the return argument of the function.
The function call requests the return of a pointer value for a byte array which is supplied.
Well .... it doesn't work .... I have checked multiple sites and I think this should work. The error message I get is:
MPU6050_I2C_rev1:232: error: incompatible types in assignment of 'byte* {aka unsigned char*}' to 'byte* [16] {aka unsigned char* [16]}'
i2cBuff1 = i2cReadBytes(mpuAdd, 0x6F, 16);
Problem 2
Ok say IF the code sample above worked. I am trying to reduce the amount of memory that I use in my sketch. By using any memory in the function even though the memory (need) is released after the function call, the function must need to reserve an amount of 'space' in some way, for when the function is called. Ideally I would like to avoid the use of static variables within the function that are duplicated within the main program.
Does anyone know the trade off with repeated function call.... i.e looping a function call with a bit shift operator, as apposed to calling a function once to complete a process and return ... an Array? Or was this this the whole point that C does not really support Array return in the first place.
Hope this made sense, just want to get the best from the little I got.
BR
Danny
This line:
byte *i2cBuff1[16];
declares i2cBuff1 as an array of 16 byte* pointers. But i2cReadBytes doesn't return an array of pointers, it returns an array of bytes. The declaration should be:
byte *i2cBuff1;
Another problem is that a static array can't have a dynamic size. A variable-length array has to be an automatic array, so that its size can change each time the function is called. You should use dynamic allocation with malloc() (I used calloc() instead because it automatically zeroes the memory).
byte* i2cReadBytes(byte i2cAdd, byte i2cReg, byte i2cNumBytes) {
byte *result = calloc(i2cNumBytes, sizeof(byte));
for (byte i = 0; i < i2cNumBytes; i ++) {
result[i] += i2cAdd + i2cReg;
}
return result;
}
I'm new to pointers and realloc. I know what is going wrong, but I don't know how to solve it.
I create a struct with an array of pointers:
struct DB_SLOT
{
MYSQL *MYSQL_Connection[10];
char *DB_NAME_Connection[10];
};
struct DB_SLOT DB_Conn_SLOT;
I allocate memory with realloc in a loop and (this is where it is getting wrong) I print the address of pointer 2 on the screens.
If I then try to realloc the same amount of memory (just for test purposes). it gives a glibc invalid pointer. Before realloc I print the address of pointer 2 again and it is not the same.
The code for this:
int MallocLoop;
for (MallocLoop = 0;MallocLoop < 10;MallocLoop++)
{
DB_Conn_SLOT.MYSQL_Connection[MallocLoop] = realloc(DB_Conn_SLOT.MYSQL_Connection[MallocLoop],(sizeof(MYSQL)));
DB_Conn_SLOT.DB_NAME_Connection[MallocLoop]=realloc(DB_Conn_SLOT.DB_NAME_Connection[MallocLoop],(sizeof(char)));
if (MallocLoop == 2)
{
printf("pointer 1 %d \n",DB_Conn_SLOT.DB_NAME_Connection[MallocLoop]);
}
DB_Conn_SLOT.DB_NAME_Connection[MallocLoop] ="\0";
}
MallocLoop = 2;
printf("pointer 2 %d \n",DB_Conn_SLOT.DB_NAME_Connection[MallocLoop]);
DB_Conn_SLOT.DB_NAME_Connection[MallocLoop] = realloc(DB_Conn_SLOT.DB_NAME_Connection[MallocLoop], (sizeof(char)));
The result of printing the address of the pointer results in 2 different addresses. How do i solve this??
You have the following two lines:
DB_Conn_SLOT.DB_NAME_Connection[MallocLoop]=realloc(...); ...
DB_Conn_SLOT.DB_NAME_Connection[MallocLoop] ="\0";
Let's simplify this to:
p = realloc(...);
p = "\0";
The first line makes p point at dynamically allocated memory block. The second line leaks that memory (you no longer have a pointer to it), and makes p point to a block of memory inside the .data section.
When you loop again, and pass the .data pointer to realloc, it correctly complains: it is not valid to pass non-dynamically allocated memory to realloc.
What you probably wanted to do was this:
p = realloc(...);
p[0] = '\0';
That makes p point to a dynamically allocated memory block, and makes that block be an empty string.
So I've been stuck on a memory problem for days now.
I have a multi-threaded program running with c++. I initialize a double* pointer.
From what I've read and previous programming experience, a pointer gets initialized to garbage. It will be Null if you initialize it to 0 or if you allocate memory that's too much for the program. For me, my pointer initialization, without allocation, gives me a null pointer.
A parser function I wrote is suppose to return a pointer to the array of parsed information. When I call the function,
double* data;
data = Parser.ReadCoordinates(&storageFilename[0]);
Now the returned pointer to the array should be set to data. Then I try to print something out from the array. I get memory corruption errors. I've ran gdb and it gives me a memory corruption error:
*** glibc detected *** /home/user/kinect/openni/Platform/Linux/Bin/x64-Debug/Sample-NiHandTracker: free(): corrupted unsorted chunks: 0x0000000001387f90 ***
*** glibc detected *** /home/user/kinect/openni/Platform/Linux/Bin/x64-Debug/Sample-NiHandTracker: malloc(): memory corruption: 0x0000000001392670 ***
Can someone explain to me what is going on? I've tried initializing the pointer as a global but that doesn't work either. I've tried to allocate memory but I still get a memory corruption error. The parser works. I've tested it out with a simple program. So I don't understand why it won't work in my other program. What am I doing wrong? I can also provide more info if needed.
Parser code
double* csvParser::ReadCoordinates(char* filename){
int x; //counter
int size=0; //
char* data;
int i = 0; //counter
FILE *fp=fopen(filename, "r");
if (fp == NULL){
perror ("Error opening file");
}
while (( x = fgetc(fp)) != EOF ) { //Returns the character currently pointed by the internal file position indicator
size++; //Number of characters in the csv file
}
rewind(fp); //Sets the position indicator to the beginning of the file
printf("size is %d.\n", size); //print
data = new char[23]; //Each line is 23 bytes (characters) long
size = (size/23) * 2; //number of x, y coordinates
coord = new double[size]; //allocate memory for an array of coordinates, need to be freed somewhere
num_coord = size; //num_coord is public
//fgets (data, size, fp);
//printf("data is %c.\n", *data);
for(x=0; x<size; x++){
fgets (data, size, fp);
coord[i] = atof(&data[0]); //convert string to double
coord[i+1] = atof(&data[11]); //convert string to double
i = i+2;
}
delete[] data;
fclose (fp);
return coord;
}
Corrupt memory occurs when you write outside the bound of an array or vector.
It's called heap underrun and overrun (depends on which side it's on).
The heap's allocation data gets corrupted, so the symptom you see is an exception in free() or new() calls.
You usually don't get an access violation because the memory is allocated and it belongs to you, but it's used by the heap's logic.
Find the place where you might be writing outside the bounds of an array.