Cloning a struct? - c

I have some structs like the below:
typedef struct {
GLubyte red, green, blue;
} pixel;
typedef struct {
pixel *pixelData;
int w, h;
} imagen;
It's for an image loader and image processor (applies filters to a loaded image).
I'm initializing two imagen:
imagen work, original;
work is something that I want to display after having some filters applied, and original is something I can reset to.
void loadImage() {
//load data into (imagen)original
}
work = original;
After loading the image, I copy it to work so I can maintain a copy of the original should I want to reset later (reset being work = original again). The problem I'm facing is that the reset doesn't work: anything I apply to work is also applied to original, so I'm effectively resetting to what I'm resetting.
I think the problem is my work = original; I'm fairly new to C, but I'm assuming I'm only pointing work at original, so any logic I do on work is also applied to original?
original.w = 40;
work = original;
work.w = 50;
work = original;
Is work.w 40 or 50 in this case? If it is indeed pointing to original, how do I instead clone original onto work, so I can safely work on work without consequence of original?

You have a pixelData pointer in your struct:
typedef struct {
pixel *pixelData;
int w, h;
} imagen;
In order to create a completely independent copy, you need to copy the data pixelData is pointing to:
work.w = original.w;
work.h = original.h;
size_t size = sizeof(pixel) * work.w * work.h;
work.pixelData = (pixel*)malloc(size);
memcpy(original.pixelData, work.pixelData, size);
Also note that when you no longer need it you have to release the allocated memory:
free(work.pixelData);

I think the problem is in the pointer to pixeldata. When you assign it, you are copying the address of the value stored in original, and once you modify it with, the original is modified too. Try allocating a new pixelData pointer and then copy the original content in its value, instead of copying the pointed address itself.

Related

Bytecopy of Float array into Byte buffer creates hard fault (C - STM32F4xx/F103)

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

C - Problems stepping through a struct pointer

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.

Accidental Pointer Reassignment in AVR Simulator

The following function, populateArpeggioArray, takes a pointer to a typedef'd struct containing several members, the identities of which are not necessarily relevant to the issue that I have. populateArpeggioArray should perform a few operations on the internal elements of the structure before passing a pointer to the struct to the function sortNoteStack.
What I've found is that the struct is never operated upon by sortNoteStack, because populateArpeggioArray, at some point, changes the value of the pointer to the struct before passing the changed value to sortNoteStack.
As far as I can tell, the code seems to be formatted properly, with proper pointer dereferencing for all operations performed on the elements of the struct. From what I can see, none of the lines of code should be able to modify the value of the pointer to the struct. Declaring the struct with the const prefix does not help, as its members are therefore also locked to a fixed value.
I'm open to the idea that this may be a problem with the simulator, and not the code, but if there is some latent issue with the code I have written, I'd certainly like to understand what I'm doing incorrectly.
Thank you for your help.
-Nick
void populateArpeggioArray(arpeggio* arp) {
uint8_t i = 0,j=0, newNoteFlag=0;
for(i=0; i<12; i++) {
newNoteFlag = 0;
if(globals.keyboardCurrentState[i]) { /* Check to see if the current state shows that a keyboard button is pressed. */
arp->sequenceLength++; /* Temporarily increase the sequence length */
for(j=0;j < arp->sequenceLength;j++) { /* Check the pitch of each note currently in the note stack */
if(globals.keyboardNotes[i] == arp->notesUnordered[j].pitch) { /* If the currently selected note is already present in the note stack, */
arp->sequenceLength--;
newNoteFlag = 1; /* undo the temporary sequence length increase */
}
}
if(!newNoteFlag) {
arp->notesOrdered[arp->sequenceLength].pitch = globals.keyboardNotes[i]+liveArpeggio.transposeShift;
arp->notesUnordered[arp->sequenceLength].pitch = globals.keyboardNotes[i]+liveArpeggio.transposeShift; /* Add the new pitch to the appended note */
arp->notesOrdered[arp->sequenceLength].length = 111;
arp->notesUnordered[arp->sequenceLength].length = 111; /* Give the new note a default length. TEMP */
}
}
}
sortNoteStack(&arp);
}
With sortNoteStack(&arp), you're passing the address of the pointer, not the address of the struct. You want to pass the address of the struct (the value of the pointer). Thus, use sortNoteStack(arp).

deep copy of struct with Pointer Point in C

i need your help!
I like to copy a struct like this:
typedef struct PackageObject_s {
long **vertex; // vertices
long num_vertex; // count of vertices
long objectType; //
REAL r; //
long bottom[3]; // bounding box bottom vector
long top[3]; // bounding box top vector
long *start; //
REAL coverage; //
} PackageObject __attribute__ ((aligned));
I try it like this:
static inline void PackageObject_copy(PackageObject *dst, const PackageObject *src) {
dst->num_vertex = src->num_vertex;
dst->objectType = src->objectType;
dst->r = src->r;
vec_assign3l(dst->bottom, src->bottom);
vec_assign3l(dst->top, src->top);
// TODO copy **vertex ???
dst->coverage = src->coverage;
dst->coverage = src->coverage;
}
How can i solve this?
Thank you in advance for your help!!
UPDATE - my solution for deepcopy of vertex - thx for all help:
dst->vertex = (long *)malloc(dst->num_vertex * 3 * sizeof(long));
for (long i=0; i < src->num_vertex; i++) {
dst->vertex[i] = (long)malloc(3*sizeof(long));
memcpy(dst->vertex[i],src->vertex[i],3 * sizeof(long));
}
I'm going to assume that the vertices are not shared between objects. That is, they belong to the structure in question.
There are two primary cases to consider:
1. Copying into a new object
2. Copying into an existing object
Copying into the new object is straightforward.
1a. Allocate space for <num_vertex> pointers.
1b. Allocate space for each vertex.
2a. Copy <num_vertex> pointers from source to destination.
2b. Copy <num_vertex> vertices from source to destination.
Copying into an existing object is much the same as copying into a new object except that you have to do the following first.
0a. Loop through each element of <vertex> and free the vertex.
0b. Free the array of vertex pointers.
1. Follow the steps for copying into a new object.
Hope this helps.
Original answer:
Assuming vertex points to an array of vertices, and that each vertice contains 3 longs (x,y,z):
dst->vertex = (long **)malloc(dst->num_vertex * 3 * sizeof(long);
memcpy(dst,src,dst->num_vertex * 3 * sizeof(long));
Update because I realized this might work but isn't clean or especially safe
As I mentioned in comments, code would be cleaner if you had
typedef struct vertextag {
long x;
long y;
long z;
} vertex_type;
And then did:
dst->vertex = (vertex_type *)malloc(dst->num_vertex * sizeof(vertex_type);
memcpy(dst,src,dst->num_vertex * sizeof(vertex_type));
It depends on whether the vertex-array should belong to the object you are trying to copy or whether it is shared among multiple objects. Both approaches are used in practice, depending on the situation (the array must be copied if the vertices can be changed for the copy-object separately). You have to choose which of them makes sense for the application you are developing.
If the array can be shared by objects pointing to them, just copy the pointer.
dst->vertex = src->vertex;
If each object has their own vertices (so they can be changed separately for the copied object) then you have to allocate and copy the array and the place where the pointer is stored and set a pointer to that place into the copy-object.
long* vertexCopy = malloc(howmanybytes);
memcpy(vertexCopy, *src->vertex, howmanybytes);
long** holder = malloc(sizeof(void*));
holder[0] = vertexCopy;
dst->vertex = holder;

Object creation: Pointer to dynamically allocated data inside a value type object - good or bad?

I have a simple struct:
typedef struct {
int width, height;
unsigned char *pixels;
} image;
Which one is the better API?
image *imagecreate(int w, int h) {
image *img = malloc(sizeof(image));
img->width = w;
img->height = h;
img->pixels = calloc(w * h, 3);
return img;
}
void imagefree(image *img) {
free(img->pixels);
free(img);
}
or
image imagecreate(int w, int h) {
image img;
img.width = w;
img.height = h;
img.pixels = calloc(w * h, 3);
return img;
}
void imagefree(image *img) {
free(img->pixels);
img->width = img->height = 0;
}
?
It seems to be overkill to do an additional malloc() for such a small struct which is only a wrapper around a pointer to the real dynamically allocated data. But on the other hand it feels unnatural (to me) to hide a pointer to dynamically allocated memory inside a value type. One could think that you don't have to free it.
You're talking about API. So it's crucial that it should be easy for your clients to use correctly and hard to use incorrectly.
A small improve on option #2
For example, if I'm the user of your second API:
image imagecreate(int w, int h);
void imagefree(image *img);
I probably won't even notice the need to call imagefree because imagecreate returns an object, not a pointer to an object, while imagefree needs a pointer. I may think that imagefree is only a wrapper of delete image for a heap allocated object. So I won't use it for a "stack" object.
Therefore, this is better:
image imagecreate(int w, int h);
void imagefree(image img);
While you have a heap-allocated member inside image, but you hide it in these APIs which is good. And they have consistent "lookings" which is better, and less error-prone.
So what about option #1?
As to your first option, is that even better? That depends (on individuals). As to me, I perfer option #1.
image *imagecreate(int w, int h);
void imagefree(image *img);
Why?
Although we don't have a way to enforce the resource auto destruction by destructor like RAII in C++, usually more attention is paid for C programmers who see a "pointer" returned from an API(we are sensitive to pointers, aren't we? ;). It's much likely that they keep asking themselves: is it dynamicly allocated inside imagecreate? Do I need deallocate it via some other API?
The difference is that your struct is allocated dynamically in the first case and automatically in the second. That's a matter of personal preference, coding standards and opinion. Second way seems safer to me because its one less free to remember to do, but since you've got to free anyway - doesn't really matter all that much.
Note that in the second case the struct is copied into the return value. You seem to be dealing with the pointer in it well, but its a potential landmine right there.
i would go with the first. assume you have a descriptor'char name[100]' in your struct, your second would use 100byte of stackspace, which must be handled by the operating system, whereas the first memory my be handled by yourself (using a selfwritten garbage collector instead of the standard malloc) and you can move the handle to the object around as you please without having to take care of your limitied stack space.

Resources