Access violation reading location location 0x1D5C4C2F - c

This function is throwing an access violation when reading raw pixel values and I can't figure out why.
Can consider this as the only part of my code running, I've run this solo with the same result.
string filenames[]={"firstclick.raw", "secondclick.raw","thirdclick.raw","fourthclick.raw","fifthclick.raw","sixthclick.raw","seventhclick.raw","eighthclick.raw"};
FILE *file;
int height= 750, width = 453, bbp=3;
unsigned char ****images;
images = (unsigned char ****)malloc(sizeof(unsigned char ***)*8);
for(int j = 0; j<8; j++){
images[j] = (unsigned char ***)malloc(sizeof(unsigned char**)*height);
for(int i = 0; i<height; i++){
images[j][i]= (unsigned char **)malloc(sizeof(unsigned char*)*width);
for(int k = 0; k<bbp; k++)
images[j][i][k]= (unsigned char *)malloc(sizeof(unsigned char)*bbp);
}
}
for (int i = 0; i<8; i++){
if (!(file=fopen(filenames[i].c_str(),"rb"))){
cout << "Cannot open file: "<<filenames[i].c_str() <<endl;
exit(1);
}
fread(images[i], sizeof(unsigned char), height*width*bbp, file);
fclose(file);
}

The problem here is you've allocated each element of your array as a separate array (somewhere else in memory, whose location is kept as a pointer). But when you read in, you assume that it's a single contiguous block. You will overwrite all those pointers, and overflow the buffer to boot.
If you want images to be a set of discrete blocks of memory, allocate like this:
unsigned char ** images;
int i;
images = malloc( sizeof(unsigned char *) * 8 );
for( i = 0; i < 8; i++ ) {
images[i] = malloc( width * height * bpp );
}
Note that sizeof(unsigned char) is defined by the standard to always be 1. You don't need to multiply by sizeof(unsigned char) all the time.
Now, to get a pixel address in an image, you need to multiply out (usually row-major):
unsigned char * pixel = images[i] + (y * width + x) * bpp;
unsigned char r = pixel[0];
unsigned char g = pixel[1];
unsigned char b = pixel[2];

when you allocate the memory blocks in different locations in memory an fread on that structure will not work.
instead allocate one big block then set the pointers to point inside the block, that way you can use fread on it.

Related

Copying unsigned char array to uint32_t, and vice versa

I'm trying to iteratively copy an unsigned char array to a uint_32t variable (in 4 byte blocks), perform some operation on the uint_32t variable, and copy it back to the unsigned char array.
Here's my code:
unsigned char byteArray[len]
for (int i=0; i<len; i+=4) {
uint32_t tmpInt = 0;
memcpy(&tmpInt, byteArray+(i*4), sizeof(uint32_t));
// do some operation on tmpInt here
memcpy((void*)(byteArray+(i*4)), &tmpInt, sizeof(uint32_t));
}
It doesn't work though. What's wrong, and how can I achieve what I want to do?
The problem is that you are adding 4 to i with each iteration and multiplying by 4. You should be using byteArray + i.
Also, as #WeatherVane pointed out below, your loop would be more consistent with a sizeof():
for (int i = 0; i < len; i += sizeof(uint32_t)).
As others pointed out you are doing too much by incrementing i as well as multiplying it by the size of your target.
On top of this
the code shown might run into a buffer overflow issue reading beyond the source array.
the sizeof operator evaluates to size_t not int.
the code repeats defining the size of the target independently several times.
Fixing all, the result might look like this:
unsigned char byte_array[len];
typedef uint32_t target_type;
const size_t s = sizeof (target_type);
for (size_t i = 0; i < (len/s)*s; i += s) {
target_type target;
memcpy(&target, byte_array + i, s);
// do some operation on target here
memcpy(byte_array + i, &target, s);
}
To avoid the typedef just define the target outside of the for-loop:
unsigned char byte_array[len];
{
uint32_t target;
const size_t s = sizeof target;
for (size_t i = 0; i < (len/s)*s; i += s) {
memcpy(&target, byte_array + i, s);
// do some operation on target here
memcpy(byte_array + i, &target, s);
}
}
An equivalent to
byte_array + i
would be
&byte_array[i]
which might be more intuitively to read.
To avoid the "strange" (len/s)*s one could step away from using an index at all, but use a pointer instead:
for (unsigned char p = byte_array; p < byte_array + len; p += s) {
memcpy(&target, p, s);
// do some operation on target here
memcpy(p, &target, s);
}
In my opinion this is a more elegant solution.

Writing 2D array into binary file in C (getting strange results)

I'm using this code to write the file:
FILE *f = fopen("out/solution.raw", "wb");
int i, j;
//SIZE = 512
for(i = 0; i < SIZE; i++)
{
fwrite(matrix[i], 1, SIZE, f);
}
fclose(f);
The problem is that when I open the file, it 3 '0' between the numbers, here are 2 screenshots to help you understand what I mean:
This is what I should be getting:
And this is what I'm getting:
As you can see my code is correctly writing each number, but there are three 0 between each number and I have no idea why.
I've also tried this:
fwrite(matrix[i], sizeof(matrix[i][0]), SIZE, f);
But none seems to work, any help would be greatly appreciated.
my matrix is declared as a 2D array of ints, as I need to do some operations with those numbers:
matrix = (int**)malloc(SIZE * sizeof(int*));
for (i = 0; i < SIZE; i++)
{
matrix [i] = (int*)malloc(SIZE * sizeof(int*));
}
I've tried your solution but I can't assign an unsiged char to an int, so I've tried casting it and I get this warning:
cast from pointer to integer of different size.
unsigned char to_write;
for(i = 0; i < SIZE; i++)
{
to_write = (unsigned char)matrix[i];
fwrite(&to_write, 1, 1, f);
}
(code used)
After that this is what I'm getting:
And btw, my data is unsigned.
matrix[i] is a pointer on 32-bit integers. Even if you assign values that hold in 8 bits, that doesn't "compress" the data when you're writing to a binary stream (plus you probably don't write the 512 values but only 512/4 = 128 values)
Your machine is little endian, so you get the LSB first, then 3 zeros, for each value.
So change the type of matrix[i] from int32_t * to char * or unsigned char * depending on what you need, make sure your values are in 8-bit range, and you can use fwrite like you're planning to.
If you cannot change the data type of matrix, use a loop to convert the values
for(i = 0; i < SIZE; i++)
{
uint8_t to_write = matrix[i]; // assign/truncate for 0/255 range
fwrite(&to_write, 1, 1, f);
}
if your data is signed, you have to use int8_t. But in that case, you're not going to be able to write a0 as 160.
EDIT: your edit shows the real type of matrix. matrix[i] is a pointer on data, so you need to use a double loop to dump it, else you're copying the address of the array, not the value
for(i = 0; i < SIZE; i++)
{
const int *row = matrix[i];
for(j = 0; j < SIZE; j++)
{
uint8_t to_write = row[j]; // assign/truncate for 0/255 range
fwrite(&to_write, 1, 1, f);
}
}

Cast void* to char*

I have a char * who points to the structure. Here is my structure:
struct prot
{
int size;
unsigned short codeAction;
void *data;
};
I recovered size and codeAction, but now I want to recover data.
And when I cast my last 8 bytes I have nothing in it.
The following code is just a test, it's a bad code:
char lol[4];
for (int i = 0; i < 4; i++)
lol[i] = test[i];
int size = *(int*)lol;
char loli[2];
int index = 0;
for (int i = 4; i < 6; i++)
{
loli[index] = test[i];
index++;
}
int code = *(short*)loli;
char lolo[8];
index = 0;
for (int i = 6; i < size; ++i)
{
lolo[index] = test[i];
index++;
}
void *newData = (char *)lolo; // how can I cast it?
How I can display the content of newData?
Your problem is that when casting lolo you actually cast a pointer to the char array you defined. So the result of the cast would be a char pointer to the first cell of the array.
Why don't you just use this as a struct and access the fields regularly?
Anyway, you want to use lolo as a 64 bit type pointer and the access what's in it.
void* newData = *((uint64_t*)lolo)
Besides, don't loop until size in the last for loop, loop only 8 times, until lolo is full. The number of bytes in newData itself (not what it points to) is constant, and is 4 bytes on 32bit machines, 8 bytes on 64bit ones.
Last thing - index++, not o++. o isn't defined, as much as I can see.

Increment Char Array Pointer

Is it possible to increment/advance a char array like I can a char pointer?
For example I can do this for a char pointer:
while (*cPtr)
printf("c=%c\n", *(cPtr++));
But I am not able to do this:
// char cArray[] = "abcde";
while (*cArray)
printf("c=%c\n", *(cArray++)); // Compile error: 19 26 [Error] lvalue required as increment operand
The purpose is to be able to iterate over a char array when I dont know the length of the array. My thinking is that I just want to advance till I find a null character I guess unless theres an easier way?
char a[] = "abcde";
int index = -1;
while (a[++index])
printf("c=%c\n", a[index]);
Is it possible to increment/advance a char array like I can a char pointer?
Unlike pointers, arrays are not lvalues and you can't modify it. That's a major difference between arrays and pointers.
Do something like that:
char cArray[] = "abc def";
char *p = &cArray[0];
while (*p)
printf("c=%c\n", *(p++));
You can do:
for(int i = 0; i < 5; i++) // if you know the length
printf("c=%c\n", a[i]);
or get the size with sizeof() and replace i < 5 with i < size:
int size = (sizeof(a) / sizeof(*a))
I have used this with success under keil uVision:
char buffer[512];
uint8_t var[512]; // uint8_t = integer 8bit
for(int i = 0; i < 128; i = i + 4)
sprintf(&buffer[i],"%03d,", var[y]); //this will put 4 bytes in buffer
Better way to do this:
char buffer[128];
uint8_t int_buffer[24]; // gets updated in an interrupt - some sensors values
uint8_t i = 0;
uint8_t PrintSize = 0;
while(/*myFile is smaller than 1Mb..*/)
{
PrintSize = 0;
i = 0;
while(i < 23)
{
PrintSize += sprintf(buffer + PrintSize,"%01d,",int_buffer[i]);
i++;
}
PrintSize += sprintf(buffer + PrintSize,"%01d\n", int_buffer[23]);
//write buffer to a file in my app
}
File content is like this:
41,1,210,243,120,0,210,202,170,0,14,28,0,0,0,1,85,0,5,45,0,0,0,1
40,1,215,255,119,0,215,255,170,0,14,37,0,0,0,1,85,0,5,46,0,0,0,1

how to create the array allocated at memory

I used the codes below to create dynamic memory.
unsigned int *mem ;
mem = (unsigned int*) malloc(mallocSize);
However, I prefer to create an array of pointers.
Each pointers will link to one of the memory block.
but I prefer to create an array of pointers each pointer links to one of the memory block above
unsigned int **mem = (unsigned int **)malloc(sizeof(unsigned int *) * number_of_pointers);
// memset(mem, NULL, sizeof(unsigned int *) * number_of_pointers); // recommend it but not needed here, we always set NULL for safety.
for (int index = 0; index < number_of_pointers; index++)
mem[index] = (unsigned int *)malloc(sizeof(unsigned int) * number_of_ints);
to access individual elements mem[row_index][column_index]
to de-allocate, to reduce or remove memory leaks.
for (int index = 0; index < number_of_pointers; index++)
free(mem[index]);
free(mem);
rule of thumb, for me anyway, free should be call as often as malloc
I guess the below code should do it for you. You can create an array of pointers and then store the pointer to each of the memory block in each element of the array. But, the important point is that if you are having an array of unsigned int *, the size passed to malloc must be sizeof(unsigned int). You can modify the below example for other types.
unsigned int *mem[100];
for (i=0; i<100; i++)
{
mem[i] = malloc(sizeof(unsigned int));
}
Arrays have always compile-time fixed size in C. If that's okay with you, use array syntax:
unsigned int *mem[NUM_PTRS];
for (int i=0; i<NUM_PTRS; i++) {
mem[i] = malloc(mallocSize);
}
If you need to decide the size at runtime, you need a pointer-to-pointer:
unsigned int **mem;
mem = malloc(sizeof(unsigned int *) * num_ptrs);
for (int i=0; i<num_ptrs; i++) {
mem[i] = malloc(mallocSize);
}
unsigned int **pMemory;
pMemory = (int**)malloc(sizeof(unsigned int *) *number_of_pointers);
for(int index_to_pointer = 0; \
index_to_pointer < number_of_pointers; \
index_to_pointer++)
{ pMemory[index_to_pointer] = (int*)malloc(sizeof(unsigned int));}
I think this is how we allocated dynamic double dimension memory allocation. hope this will help the purpose.

Resources