This is fairly elementary and I'm probably missing something really obvious, but this one has me a bit stumped. Basically, let's say I'm trying to turn an entire PPM image red (that's not actually what I'm doing, but for the sake of troubleshooting, we'll go with that). I have a struct that I'm using to store the pixel values in.
typedef struct pixel_type
{
unsigned char r;
unsigned char g;
unsigned char b;
} pixel_t;
The pointer that I am using to point to that struct is "buffer."
pixel_t *buffer;
Which I have also allocated the amount of space I need for (the width of the image * the height of the image * the number of pixel values [3] )
buffer = malloc(WIDTH*HEIGHT*sizeof(pixel_t));
I then have a 'for' loop which I am using to step through the buffer pointer and convert every pixel value to red.
int i;
for (i=0;i<(WIDTH*HEIGHT);i++){
buffer->r=255;
buffer->g=0;
buffer->b=0;
buffer++;} //this part appears to be the problem
The problem here is the output is just a black image with a few garbage pixels right at the top. I have also tried taking out the 'buffer++," and the first pixel appears to be converted to red with no issues. However, when I put it back in, NONE of the pixels are red (not even the first one).
I am not sure what I'm missing. I know that when you create a pointer, you can step through to the next address of the pointer simply by doing the pointer (without a * dereference) with a '++' at the end. Nevertheless, this seems to be the issue. Can someone tell me what I'm doing wrong?
Thanks again,
Austin
I think the problem is that you are not storing the initial value of the buffer pointer that you have allocated. You increment the pointer in a loop as you go, so buffer points to the end of the buffer after the loop is over.
Use a different pointer in your loop to fix this problem:
int i;
pixel_t *ptr;
for (i=0, ptr = buffer;i<(WIDTH*HEIGHT);i++){
ptr->r=255;
ptr->g=0;
ptr->b=0;
ptr++;}
The first concept to realize is that buffer is a pointer to the storage for your array of pixels. It is the ONLY pointer to that storage. If code modifies buffer then that start of that storage is no longer easily accessed.
Secondly, you want to keep buffer set at its original value so that malloc can be reversed. Thus, keep two pointers to access the array of pixels. One of them is the "anchor" the other the indexer:
pixel_t *buffer, *pix;
buffer = malloc(WIDTH*HEIGHT*sizeof(pixel_t));
for (pix = buffer; pix < buffer + (WIDTH*HEIGHT); pix++)
{
pix->r = 255;
pix->g = 0;
pix->b = 0;
}
// later in your code
free(buffer);
So, try this.
Related
Abstract:
I need to copy all elements of a struct containing a float array into a byte buffer, in order to send it out via UART. The next call of malloc after the copy operation leads (allways) to a hard fault, which is a good indicator that somewhere the memory gets corrupted, but I have no clue where this could happen (after 2 days debugging ...)
Description:
I have a nested Typtedef, that contains a float array:
#define DRV_SCALE_MAXSZ 32
#define DRV_CHANNELS 2
typedef struct {
float x1;
float step;
uint8_t aSz;
float Y[DRV_SCALE_MAXSZ];
} DRV_linscale_TDS;
typedef struct {
DRV_linscale_TDS scale;
uint32_t active;
} DRV_ChScale_TDS;
DRV_ChScale_TDS DRV_scale[DRV_CHANNELS] = {0,}; // Channel Scales
And I need to copy the whole content of either DRV_scale[0] or [1] into a byte buffer, in order to send it out via UART.
As a little extra complication I copy it element by element, with a copy function, that reverts the bytes of the value if necessary:
#define TXBUFSZ 255
volatile uint8_t TxBuf[TXBUFSZ] = {0,};
void FillTxBuf(uint8_t idx, uint8_t *pBo) {
if(idx < DRV_CHANNELS) {
volatile uint8_t *pDst = TxBuf;
*pDst++ = DRV_SCALE_MAXSZ;
*pDst++ = DRV_scale[idx].active;
pDst += COM_ElementCopyU32((uint8_t*)&DRV_scale[idx].scale.x1, pDst, pBo);
pDst += COM_ElementCopyU32((uint8_t*)&DRV_scale[idx].scale.step, pDst, pBo);
*pDst++ = DRV_scale[idx].scale.aSz;
uint8_t i = *pDst;
float *pSrc = DRV_scale[idx].scale.Y;
while(i--) {
pDst += COM_ElementCopyU32((uint8_t*)pSrc, pDst, pBo);
pSrc++;
}
}
}
Note: the code above is a shrinked version just for explanation. In reality TxBuf[TXBUFSZ] is a static preallocated byte buffer (declared extern in the header file, and defined in the c file)
The function COM_ElementCopyU32 looks like this:
uint8_t COM_ElementCopyU32(volatile uint8_t* pSrc, volatile uint8_t* pDst, uint8_t* ByteOrder) {
// #brief copy data from Source to Destination and revert bytes if necessary
// #param U8* pSrc: Pointer to data Source Buffer
// #param U8* pDst: Pointer to Destination Buffer
// #param U8 ByteOder: 0 = little endian, 1=big endian
// #return u16 number of copied bytes
if(pSrc && pDst) {
if(*ByteOrder != isBigEndian) {
pDst[0] = pSrc[3];
pDst[1] = pSrc[2];
pDst[2] = pSrc[1];
pDst[3] = pSrc[0];
} else {
pDst[0] = pSrc[0];
pDst[1] = pSrc[1];
pDst[2] = pSrc[2];
pDst[3] = pSrc[3];
}
}
return(sizeof(uint32_t));
}
The issue:
as soon as the line
pDst += COM_ElementCopyU32((uint8_t*)pSrc, pDst, pBo);
is involved, the call of FillTxBuf() leads to an hard fault with the next call of malloc(). The next malloc() comes immediately after FillTxBuf() when the CRC32 is appended to the byte stream. The general workflow is: check the incoming request, fill the Tx Buffer, append the CRC32 and send it out.
What have i tried to solve this so far?
Well, i tried a lot:
I removed the line mentioned above. As long i do not copy any bytes
from DRV_scale[idx].scale.Y to TxBuf[] in the while loop is
disabled, anything works fine.
I replaced float pSrc = DRV_scale[idx].scale.Y; with * float pSrc =
DebugArray; where DebugArray is a "stand alone" static pre-allocated
float array of the same size as DRV_scale[idx].scale.Y (32
Elements) and anything works fine
I tried to copy the Elements from DRV_scale[idx].scale.Y to
another float array (lets call it "DupArray"), which worked fine but
when I tried to copy "DupArray" bytewise into TxBuf[] it crashes.
and I tried to copy the Elements from DRV_scale[idx].scale.Y to
TxBuf[] in another function, right after Hardware initialisation, using the same code (copy & paste), it worked fine
I tried several versions of the DRV_linscale_TDS Typdef, with the
Byte variable at the end and at the beginning, with no effect
I checked if there would be a buffer overflow in the while loop, but
as expected there is none, as the total number of copied bytes is
~100, so there are 155 bytes "free" (note: the overrun prevention
code is still in the original code but left out here for better
readability)
I have no clue what's going on here. Each part of the code - when I debug it separatey - works fine. Copying the original Array to another float preallocated float array works fine, copying the float array to a byte array and writing it back works fine. Just if I do exactly that, whats working fine verywhere else, in that particular function, it generates a hard fault.
Through all the testing and debugging it points out clearly: the hard fault only happens, when I try to copy DRV_scale[idx].scale.Y into TxBuf[], anything else works without problems.
One might say: well, then somewhere before FillTxBuf() TxBuf[] gets corrupted, but why works anything flawless in FillTxBuf() when I use a different float array than DRV_scale[idx].scale.Y?
Remarks:
One possible workaround would most probably be to split up the struct and use separate preallocated "stand alone" float arrays. The reason why I glued it together in one variable is, that this variable is written to flash and I'd really like the approach FlashWrite(VariablePointer, SizeInBytes) ...
If there is no other option, i will have to separate it, but I'd really like to understand in which pitfall I stumbled in ...
The Question:
Where could I search?
I have no idea about the problem but you can use union to send struct data within a array. Here is an example;
typedef union
{
your struct object; (should be packed
struct)
uint8_t uartBuff[your struct size];
}unExample;
Variables in union use same memory address via this you can easily send your data.
hardfault errors always because of pointer-alingment
i usually use my own library for binary serialize in c
this library can help you
it's have examples in c and for STM32F4 already
it's support endiness and have configuration part for customization
I am writing in C on a BeagleBone Black MCU.
I need to create a 2D unsigned int array to store some collected analog data from two sensors.
Currently I have individual unsigned int arrays for each sensor's data but I'd like to change this to have one variable that is 2 dimensions with one dimension being the sensor the data originated from.
Here's what I have so far and it works just fine. (Apologies if this isn't formatting correctly. I tried to bold the code but it doesn't seem to work in Chrome the way I'd expect.)
#define SHARE_MEM 0x10000
#define E_RING_BUFFER_SIZE 200
volatile unsigned int *DetTSampleSet = (unsigned int *) SHARE_MEM;
volatile unsigned int *DetBSampleSet = (unsigned int *) (SHARE_MEM + (E_RING_BUFFER_SIZE * sizeof(unsigned int)));
I believe this code ensures that DetBSampleSet is located immediately after DetTSampleSet with no overlap. It works fine. I am able to use these variables like this.
int pnr;
for (pnr = 0; pnr <10;pnr++)
{
// do some stuff to get RawAnalog from sensor T.
DetTSampleSet[pnr] = RawAnalog;
// do some stuff to get RawAnalog from sensor B.
DetBSampleSet[pnr] = RawAnalog;
}
What I want is this.
int pnr;
for (pnr = 0; pnr <10; pnr++)
{
// do some stuff to get RawAnalog from sensor T (0)
DetSampleSet[0][pnr] = RawAnalog;
// do some stuff to get RawAnalog from sensor B (1)
DetSampleSet[1][pnr] = RawAnalog;
I think I can just declare this as the first variable in this memory space like this.
#define SHARE_MEM 0x10000
#define E_RING_BUFFER_SIZE 200
volatile unsigned int *DetSampleSet = (unsigned int *) SHARE_MEM
If I do then, I don't think I have to worry about how this data is actually structured in memory as in
are the first four bytes DetSampleSet[0][0] and the next four bytes DetSampleSet[0][1] or DetSampleSet[1][0] because I don't plan to access this data with any pointers/addresses?
However, if I want to declare another variable in memory adjacent to this variable with no overlap, do I just double the size offset like this?
volatile unsigned int *NewIntVariableAfterFirstOne = (unsigned int *) (SHARE_MEM + (E_RING_BUFFER_SIZE * 2 * sizeof(unsigned int)));
Thanks for any and all help and your patience as I'm getting back into C after nearly 30 years.
I appreciate the comments and answers. I've tried to post a response but it seems I can't comment at length but have to add to my original question. So here goes...
So, I readily admit to getting lost sometimes in the declaration of pointers like this. The original code I posted works fine. I need to declare multiple variables in this memory space so my primary concern is to declare them properly so as to not overwrite one. Basically, ensure the start of the next variable declared is past the end of the one declared prior. So, for example, if the pointer to integer variable A is to be used as a 1-D array of X elements, then Xsizeof(int) should be a safe start of the next variable, say integer variable B. Right? And if I want to use variable A as an array to be accessed as a 2-D array, then I would just do 2X*sizeof(int) to get the start of the next variable after A, right?
Supposing that it is a valid and appropriate thing in the first place, according to your C implementation, to create a pointer value in the way you are doing, what you need is a to declare your pointer as a pointer to an array, and cast appropriately:
#define SHARE_MEM 0x10000
#define E_RING_BUFFER_SIZE 200
volatile unsigned int (*DetSampleSet)[E_RING_BUFFER_SIZE] =
(unsigned int (*)[E_RING_BUFFER_SIZE]) SHARE_MEM;
You should then be able to access the block by doubly indexing DetSampleSet, just as you say you want, with all the values for DetSampleSet[0] laid out in memory contiguously, and immediately preceding those for DetSampleSet[1].
I would rather suggest to use when accessing hardware fixed size integers
You can use the pointer to array:
#define SHARE_MEM 0x10000
#define E_RING_BUFFER_SIZE 200
typedef int32_t buff[E_RING_BUFFER_SIZE];
#define DetSampleSet ((volatile buff *)SHARE_MEM)
//example usage
int32_t foo(size_t sample, size_t sensor)
{
return DetSampleSet[sensor][sample];
}
#define is used to avoid unnecessary memory reads.
https://godbolt.org/z/c45rKvvvh
EDIT. The comments have changed the requirements. You need to change linkerscript.
Add memory area (length gas to be set by you as I do not know how bit it is):
MEMORY
{
/* the stuff which was already here */
SHAREDMEM (rw) : ORIGIN = 0x10000, LENGTH = 32M
}
In the sections add new section
.shared_mem_section (NOLOAD):
{
shared_mem_section_start = .;
KEEP(*(.shared_mem_section))
KEEP(*(.shared_mem_section*))
shared_mem_section_end = .;
} > SHAREDMEM
In your C code:
unsigned __attribute__((section(".shared_mem_section"))) DetSampleSet[NSENSORS][E_RING_BUFFER_SIZE];
UPDATE IN BOTTOM====
So a while ago I made the following function, which I successfully used to get the grey values from images (w x h dimension) that were converted to .bin-files. It just gives an array of all pixel values.
It was, however, not as a function like this but put in the main() immediately.
// read the BIN-file as grayscale image
void decodeBIN(const char* filename, short image[], int w, int h){
int i = 0;
unsigned char buffer[16]; // no specific size attributed
FILE *ptr;
ptr = fopen(filename, "rb");
if (!ptr){
printf("\nUnable to open file!\n"); // error
}
while (!feof(ptr)){
fread(buffer,2,1,ptr); // read w bytes to buffer
image[i] = buffer[1];
//printf("%u ", image[i]); // DEBUG
i++;
}
fclose(ptr);
printf("\nBinary image read (npixels: %i).\n", i-1); // DEBUG
}
I decided to expand the code, so I rewrote it to the previous function and put it in a separate file for functions and also made a header file. The extra file for functions and the header file work 100% so that's not the issue. Now, this code does not work anymore and I get a stack smashing error. Some variables called after this function have also jumped to another value, so I figured the problem was with the buffer (I didn't know about the correct size for the buffer, but it worked...). After some experimentation and testing, I came up with the following function. I replaced the buffer with a char array named image2 to simply try and test it:
void decodeBIN(const char* filename, short image[], int w, int h){
int i = 0, res;
char image2[];
FILE *ptr;
ptr = fopen(filename, "rb"); //"MySnap_20180327-2239-010.bin"
if (!ptr){
printf("\nUnable to open file!\n"); // error
}
res = fread(image2,1,w*h,ptr) // need to read w*h pixels
while (i < w*h){ // DEBUG
printf("%i ", (int)image2[i]); // DEBUG
i++;
}
printf("\nRead %u bytes\n", res); // DEBUG
fclose(ptr);
printf("Binary image read (npixels: %i).\n", i); // DEBUG
}
I'm a bit lost in how it used to work and all of a sudden when I move the code from main() to a function it stops working, so any help is welcome!
Thanks in advance.
Disclaimer: I'm aiming to write this with the help of as few libraries as possible
===== UPDATE:
After the answer of #alainmerigot I got this code, which helped with getting the correct values:
void decodeBIN(const char* filename, unsigned char image[], int w, int h){
int i = 0, res;
FILE *ptr;
res = fread(image,sizeof(char),w*h,ptr) // need to read w*h pixels
fclose(ptr);
}
The segmentation fault and jumped variables are still in place though, so here a more upper-level oversight of what I'm doing:
char filenamePathed["[path of file]/file.bin"];
short img1[npixels]; // npixels = w*h
printf("i_file: %i\n", i_file); // correct value
decodeBIN(filenamePathed, img_curr, w, h); // decode bin
printf("i_file: %i\n", i_file); // value jumped
while (i < npixels){
img1[i] = (short)img_curr[i];
i++;
}
Perhaps it is good to know that I'm doing this iteratively for multiple files (time series)? I also need it to end up in a (short) format (or integer, but eventually needs to be memory-efficient and pixels have a range of 0-255 so int is a bit abundant imo).
The problem with your second function is that you write in array image2 while no space has been reserved for it. Declaring char image2[]; only says that an array exists and that the address of this array can be found in var image2, but no space is associated with it, hence the problem.
You can associate space with this array by several means.
Using permanent storage in the heap
image2 = malloc(x*y); // but do not forget to free(image2) at the end of the function
Using temporary storage in the stack (space is automatically freed when leaving the function).
image2 = alloca(x*y); // slightly faster than malloc and do not require to free() the image
But the best is to use a array with parametrized size (since C99). Your array should be declared as
char image2[w*h]; // will use the value of w and h to define array size
If you want to do other things than printing the image values in your function, you should store the image in permanent memory and have a mean to know the address of the array in your program. This is probably what you intended and is the reason why you have short image[] in your parameter list.
The solution is just simply to use image instead of image2 in fread().
But, the declaration of image should be coherent and image should be an array of char not short.
Beware also of declarations. In your first function, the image is an array of unsigned char and in the second an array of char. While the storage size is identical and fread() will store the same values, they are not equivalent. If used in an arithmetic context, image[i] will be interpreted differently and the results will likely be different. In general, images are unsigned.
Apparently, the problem was with the allocation of image, although I'm not sure why it was wrong.
I used to allocate it with unsigned char image[npixels]; and the solution to the error appeared to be unsigned char image[npixels*7];
Somehow it works, but if anyone has an explanation, please do so :)
I'm creating an image compressor for a project. I generate codes for the values in the image in such a way that for every grey value (from 0-254) there is a char* code in an array called codeArray (Huffman Encoding).
A requirement is to have a function which returns unsigned char*. I go through every pixel and convert the grey value of that pixel to a code using the codeArray.
I need to make the unsigned char array grow dynamically as more grey values are converted and concatenated to the end of the array.
unsigned char* encodedString = malloc(sizeof(char));
int width = image->width; //width and height of image structure
int height = image->height;
int row, col;
for(row = 0; row<height; row++)
for(col = 0; col<width; col++)
{
int value = image->pixel[row][col]; //gets the grey value
encodedString = realloc(encodedString, (strlen(encodedString)+strlen(codeArray[value])));
strcat(encodedString, codeArray[value]);
}
I tried running this with a print statement after the strcat and found it printed until there were 24 characters then started printing garbage and then Seg faulted.
Help appreciated!
You call strlen(encodedString) on an uninitialized buffer. This is undefined behaviour. You need to zero-terminate the initial contents of encodedString.
unsigned char* encodedString = malloc(1);
//check for malloc errors
encodedString[0] = '\0';
It looks like you get away with that error, but then immediately commit another one. Your realloc makes space for strlen(encodedString)+strlen(codeArray[value]) but you have forgotten to allocate room for the zero terminator. Presumably that's what causes strcat to bomb. Fix that problem by adding one to the size parameter to realloc.
As #Lou points out the performance of your realloc strategy may be poor. You may be better to allocate the buffer once at the beginning of the function since presumably you can put a relatively tight upper bound on its size.
And you also should not ever write ptr = realloc(ptr, ...) since you won't be able to recover from a failure of realloc and will always leak. But that's really a nuance in comparison to the other faults.
I am working with a 2-dimensional array of structs which is a part of another struct. It's not something I've done a lot with so I'm having a problem. This function ends up failing after getting to the "test" for-loop near the end. It prints out one line correctly before it seg faults.
The parts of my code which read data into a dummy 2-d array of structs works just fine, so it must be my assigning array to be part of another struct (the imageStruct).
Any help would be greatly appreciated!
/*the structure of each pixel*/
typedef struct
{
int R,G,B;
}pixelStruct;
/*data for each image*/
typedef struct
{
int height;
int width;
pixelStruct *arr; /*pointer to 2-d array of pixels*/
} imageStruct;
imageStruct ReadImage(char * filename)
{
FILE *image=fopen(filename,"r");
imageStruct thisImage;
/*get header data from image*/
/*make a 2-d array of of pixels*/
pixelStruct imageArr[thisImage.height][thisImage.width];
/*Read in the image. */
/*I know this works because I after storing the image data in the
imageArr array, I printed each element from the array to the
screen.*/
/*so now I want to take the array called imageArr and put it in the
imageStruct called thisImage*/
thisImage.arr = malloc(sizeof(imageArr));
//allocate enough space in struct for the image array.
*thisImage.arr = *imageArr; /*put imageArr into the thisImage imagestruct*/
//test to see if assignment worked: (this is where it fails)
for (i = 0; i < thisImage.height; i++)
{
for (j = 0; j < thisImage.width; j++)
{
printf("\n%d: R: %d G: %d B: %d\n", i ,thisImage.arr[i][j].R,
thisImage.arr[i][j].G, thisImage.arr[i][j].B);
}
}
return thisImage;
}
(In case you are wondering why I am using a dummy array in the first place, well it's because when I started writing this code, I couldn't figure out how to do what I am trying to do now.)
EDIT: One person suggested that I didn't initialize my 2-d array correctly in the typedef for the imageStruct. Can anyone help me correct this if it is indeed the problem?
You seem to be able to create variable-length-arrays, so you're on a C99 system, or on a system that supports it. But not all compilers support those. If you want to use those, you don't need the arr pointer declaration in your struct. Assuming no variable-length-arrays, let's look at the relevant parts of your code:
/*data for each image*/
typedef struct
{
int height;
int width;
pixelStruct *arr; /*pointer to 2-d array of pixels*/
} imageStruct;
arr is a pointer to pixelStruct, and not to a 2-d array of pixels. Sure, you can use arr to access such an array, but the comment is misleading, and it hints at a misunderstanding. If you really wish to declare such a variable, you would do something like:
pixelStruct (*arr)[2][3];
and arr would be a pointer to an "array 2 of array 3 of pixelStruct", which means that arr points to a 2-d array. This isn't really what you want. To be fair, this isn't what you declare, so all is good. But your comment suggests a misunderstanding of pointers in C, and that is manifested later in your code.
At this point, you will do well to read a good introduction to arrays and pointers in C, and a really nice one is C For Smarties: Arrays and Pointers by Chris Torek. In particular, please make sure you understand the first diagram on the page and everything in the definition of the function f there.
Since you want to be able to index arr in a natural way using "column" and "row" indices, I suggest you declare arr as a pointer to pointer. So your structure becomes:
/* data for each image */
typedef struct
{
int height;
int width;
pixelStruct **arr; /* Image data of height*width dimensions */
} imageStruct;
Then in your ReadImage function, you allocate memory you need:
int i;
thisImage.arr = malloc(thisImage.height * sizeof *thisImage.arr);
for (i=0; i < thisImage.height; ++i)
thisImage.arr[i] = malloc(thisImage.width * sizeof *thisImage.arr[i]);
Note that for clarity, I haven't done any error-checking on malloc. In practice, you should check if malloc returned NULL and take appropriate measures.
Assuming all the memory allocation succeeded, you can now read your image in thisImage.arr (just like you were doing for imageArr in your original function).
Once you're done with thisImage.arr, make sure to free it:
for (i=0; i < thisImage.height; ++i)
free(thisImage.arr[i]);
free(thisImage.arr);
In practice, you will want to wrap the allocation and deallocation parts above in their respective functions that allocate and free the arr object, and take care of error-checking.
I don't think sizeof imageArr works as you expect it to when you're using runtime-sized arrays. Which, btw, are a sort of "niche" C99 feature. You should add some printouts of crucial values, such as that sizeof to see if it does what you think.
Clearer would be to use explicit allocation of the array:
thisImage.arr = malloc(thisImage.width * thisImage.height * sizeof *thisImage.arr);
I also think that it's hard (if even possible) to implement a "true" 2D array like this. I would recommend just doing the address computation yourself, i.e. accessing a pixel like this:
unsigned int x = 3, y = 1; // Assume image is larger.
print("pixel at (%d,%d) is r=%d g=%d b=%d\n", x, y, thisImage.arr[y * thisImage.width + x]);
I don't see how the required dimension information can be associated with an array at run-time; I don't think that's possible.
height and width are undefined; you might want to initialise them first, as in
thisImage.height = 10; thisImage.width = 20;
also,
what is colorRGB?
*thisImage.arr = *imageArr; /*put imageArr into the thisImage imagestruct*
This won't work. You have to declare arr as colorRGB **, allocate it accordingly, etc.
it looks like you are trying to copy array by assignment.
You cannot use simple assignment operator to do that, you have to use some function to copy things, for example memcpy.
*thisImage.arr = *imageArr;
thisimage.arr[0] = imagearr[0];
The above statements are doing the same thing.
However this is not most likely what causes the memory corruption
since you are working with two dimensional arrays, do make sure you initialize them correctly.
Looking at the code, should not even compile: the array is declared as one-dimensional in your image structure but you refer to as two-dimensional?