Casting integer to uint8_t - c

I am trying to write a small function that calculates difference for each pixel. However, seems like casting int to uint8_t ( (uint8_t)temp ) is causing problems on a microprocessor at the very first iteration and leads to a restart
abs_diff = (uint8_t*)malloc(320*240 * sizeof(uint8_t));
for (int i = 0; i < 320*240; i++){
int temp = abs((int)_jpg_buf[i] - (int)_jpg_buf_prev[i]);
Serial.printf("abs %d\n", temp);
abs_diff[i] = (uint8_t)temp; // <- fails
}
P.S. not a C expert here

Related

float values of array are not assigned during a for loop (STM32 / arm-none-eabi-gcc)

I want to convert a bunch of uint16_t values from an ADC into floating point voltages.
For this I use a for loop to loop through the uint16_t array and write the values to a float array.
But the float array remains 0 as if no assignment is ever made.
Outside of the for loop the conversion works.
And when I step through the program with the debugger, I see reasonable float values but they do not end up being written to the array. Why?
the temporary float value is clearly 1.847:
the temporary array index is clearly 0:
so I expect the adc_voltages[0] to be 1.847 which it is not:
Code:
Global Variables:
volatile uint16_t adc_dma_buffer[SG_MK2_ADC1_CHANNELS * SG_MK2_ADC1_N_SAMPLES];
float adc_voltages[SG_MK2_ADC1_CHANNELS * SG_MK2_ADC1_N_SAMPLES];
Later in the main():
float temp = 0.0f;
uint8_t index = 0;
for(uint8_t i=0; i<8; i++){
temp = BSP_convU1(adc_dma_buffer[i*SG_MK2_ADC1_CHANNELS+0]);
index = i*SG_MK2_ADC1_CHANNELS+0;
adc_voltages[index] = temp; // BSP_convU1(adc_dma_buffer[i*SG_MK2_ADC1_CHANNELS+0]);
adc_voltages[i*SG_MK2_ADC1_CHANNELS+1] = BSP_convU2(adc_dma_buffer[i*SG_MK2_ADC1_CHANNELS+1]);
adc_voltages[i*SG_MK2_ADC1_CHANNELS+2] = BSP_convU3(adc_dma_buffer[i*SG_MK2_ADC1_CHANNELS+2]);
adc_voltages[i*SG_MK2_ADC1_CHANNELS+3] = BSP_internalTemperature(adc_dma_buffer[i*SG_MK2_ADC1_CHANNELS+3]);
}
Where the functions return float:
float BSP_convU1(uint32_t adc_val){
float adc_vsense = SG_MK2_ADC_VREF/4096.0f * (float)adc_val;
return adc_vsense * BSP_CONV_U1_FACTOR + BSP_CAL_U1_OFFSET;
}
Edit:
Thanks for all the comments and good practice hints that I will use from now on. Especially with the usage of 2D arrays.
I was just able to resolve the issue.
I am still not sure why it happened.
"working outside of the loop" was not correct either, it only worked, when BSP_conv_I_MPPT() was evaluated inside the printf statement directly.
Anyhow, the following code with 2D arrays now works.
if(flag_SDADC_cplt){
flag_SDADC_cplt=0;
for(int i=0; i<SG_MK2_SDADC1_N_SAMPLES; i++){
adc_currents[i][0] = BSP_conv_I_Boost (sdadc_dma_buffer[i][0]);
adc_currents[i][1] = BSP_conv_I_MPPT (sdadc_dma_buffer[i][1]);
adc_currents[i][2] = BSP_conv_I_Solar (sdadc_dma_buffer[i][2]);
// order: adc[sample][channel]
}
printf("DCDC\tMPPT\tPV\n");
printf("%.3fA\t%.3fA\t%.3fA\n", adc_currents[0][0], adc_currents[1][0], adc_currents[2][0]); // order[channel][sample]
}
if(flag_ADC_cplt){
flag_ADC_cplt = 0;
for(int i=0; i<SG_MK2_ADC1_N_SAMPLES; i++){
adc_voltages[i][0] = BSP_convU1(adc_dma_buffer[i][0]);
adc_voltages[i][1] = BSP_convU2(adc_dma_buffer[i][1]);
adc_voltages[i][2] = BSP_convU3(adc_dma_buffer[i][2]);
adc_voltages[i][3] = BSP_internalTemperature(adc_dma_buffer[i][3]);
}
printf("\nPV\tCAN\tBat\tTemp\n");
printf("%.2fV\t%.2fV\t%.2fV\t%.1fC\n", adc_voltages[0][0], adc_voltages[0][1], adc_voltages[0][2], adc_voltages[0][3]);
}

Value changes in a struct when editing another struct in another function

I've run into a problem with structs which I believe is caused by incorrect mallocs, or possibly rather my reallocs. I've cut down the code as much as possible to only show what I believe could be relevant, so nearly all the actual operations are omitted.
The struct I have looks as follows:
struct poly_t {
int nvars, *factor, *exp;
};
The value that's acting weird is nvars, which to me would signify that I'm somehow not reserving memory properly. What I do is that I first have a function that creates and fills the struct, then I have another function where I send two of these structs in and create a third identical struct. When editing the value of nvars in this third struct, it very rarely also edits the value of nvars in the first struct. When running gdb, it shows the exact row it happens on is when I do thirdp->nvars++; in my mul function.
So with this function I create my first and second structs (a and b).
poly_t* new_poly_from_string(const char* a){
struct poly_t* p = malloc(sizeof(struct poly_t));
p->nvars = 0;
p->factor = malloc(strlen(a) * sizeof(int));
p->exp = malloc(strlen(a) * sizeof(int));
for (int i = 0; i < strlen(a); i++){
//do stuff to put a into p, using at most p->factor[p->nvars] and the same for p->exp
p->factor = realloc(p->factor, p->nvars*sizeof(int));
p->exp = realloc(p->exp, p->nvars*sizeof(int));
printf("%d", p->nvars); //At this point, nvars is the correct value
return p;
}
And below is the function that works in 9/10 cases but in some rare cases it doesn't. I've marked the exact row that changes a->nvars with an arrow -->.
poly_t* mul(poly_t* a, poly_t* b){
struct poly_t* thirdp = malloc(sizeof(struct poly_t));
thirdp->nvars = 0;
thirdp->factor = malloc((a->nvars + b->nvars) * sizeof(int));
thirdp->exp = malloc((a->nvars + b->nvars) * sizeof(int));
for (int i = 0; i < a->nvars; i++){
for (int j = 0; j < b->nvars; j++){
for (int k = 0; k < p->nvars; k++){
if (p->exp[k] == a->exp[i] + b->exp[j]){
p->factor[k] += a->factor[i]*b->factor[j];
found = 1;
break;
}
}
if (!found){
p->factor[p->nvars] = a->factor[i]*b->factor[j];
p->exp[p->nvars] = a->exp[i] + b->exp[j];
--> p->nvars++; //This is the row that changes a->nvars according to gdb
}
}
}
return thirdp;
}
Here's what I got when running gdb while trying to figure out what was changing a->nvars. Note that p is the same as thirdp above, I just renamed it here for clarity.
edit: Readded the actual code in the mul function
You are allocating space for the sum of the number of integers
a->nvars + b->nvars
I wonder what you do in
//fill thirdp->factor and thirdp->exp
As you have nested for loops I suspect you may be generating
a->nvars * b->nvars //multiply
items and hence running off the end of allocated space. You now show us the code and we see
if (!found){
// --- here ----
p->factor[p->nvars] = a->factor[i]*b->factor[j];
p->exp[p->nvars] = a->exp[i] + b->exp[j];
p->nvars++;
}
At the point I mark here you should check the value of p->nvars, I think it has the possibility to reach a value greater than (a->nvars + b->nvars).
I think to be safe allocate the space for (a->nvars * b->nvars) ints.
The problem was as I believed in the mallocs. Specifically the following two rows:
thirdp->factor = malloc((a->nvars + b->nvars) * sizeof(int));
thirdp->exp = malloc((a->nvars + b->nvars) * sizeof(int));
I simply wasn't allocating enough memory which caused the weird behaviour. What I wanted was:
thirdp->factor = malloc((a->exp[0] + b->exp[0]) * sizeof(int));
thirdp->exp = malloc((a->exp[0] + b->exp[0]) * sizeof(int));
Unfortunately since I didn't give any of the indata, or really much context, you guys probably couldn't have figured that out <.< Sorry!

Malloc affecting random integer value

I'm writing a virtual memory simulator in C, compiling on linux, and I'm getting something rather strange. It takes in a file IO, which I put into an int* plist.
I've printed this "plist" array, and it comes out to
0 100
1 200
2 400
3 300
etc
The problem is that it seems malloc or something is randomly changing plist[3] to 0. It doesn't seem like it should be that way, but I've put a print statement at every line of code to print plist[3], and
tables[i].valid = (char*) xmalloc(num_pages * sizeof(char));
is where it changes. plist[3] = 300 before the line, 0 after it. And it only does this when i = 2. The first 3 rounds of the loop run fine, and on round 3, it changes the values for round 4. I have no idea why, it makes little sense that malloc would change a value in an array that's completely unrelated - is it possible I've gone over some space limit, even though I'm using the heap for basically everything? Would it just change values in random arrays if I did?
for(i = 0; i < 4; i++){
num_pages = plist[i] / P1;
tables[i].page_num = (char**) xmalloc(num_pages * sizeof(char*));
tables[i].valid = (char*) xmalloc(num_pages * sizeof(char));
//initialize page numbers and valid bits
for(j = 0; j < 10; j++){
tables[i].page_num[j] = (char*) xmalloc(16*sizeof(char));
tmp = itoa(i, tmp);
strcat(tables[i].page_num[j], tmp);
strcat(tables[i].page_num[j], "p");
tmp = itoa(j, tmp);
strcat(tables[i].page_num[j], tmp);
tables[i].valid[j] = 0;
}
}
Here's the struct for tables:
typedef struct s_page_table
{
char** page_num;
char* valid;
} t_page_table;
And this is xmalloc (it's just a wrapper to make it easier):
void* xmalloc(int s)
{
void* p;
p = malloc(s);
if (p == NULL)
{
printf("Virtual Memory Exhausted");
exit(1);
}
return p;
}
EDIT: If I take out both lines referencing tables[i].valid, the problem does not exist. plist[3] stays the same. num_pages is always >= 10. I set j to be 0 to 10 just to have less output for debugging purposes.
EDIT 2: If I change valid from a char* to an int* it doesn't work. If I change it to an int, it does.
There are several possibilities, including (but not limited to):
tables[i] is out of bounds;
plist contains a dangling pointer (i.e. it's been deallocated);
plist hasn't been initialised;
plist isn't as large as you think, i.e. plist[3] is out of bounds.
If you can't figure out the problem by looking at the code, valgrind is your friend.
OK. So I believe the problem turned out to be playing with the strings before initializing everything. I'm not entirely certain the reason, maybe someone else can elaborate, but when I encapsulated JUST the initialization in its own function, like only doing mallocs, and then separately created the strings afterwards, the plist variable was unaffected.
For those interested, the encapsulated function looked like this:
t_page_table* table_builder(int* p, int x, int num_tables)
{
t_page_table* ret = xmalloc(num_tables * sizeof(*ret));
int i, tmp, j;
for(i = 0; i < num_tables; i++){
tmp = (p[i]/x);
ret[i].page_num = xmalloc(tmp * sizeof(char*));
ret[i].valid = xmalloc(tmp * sizeof(char));
for(j = 0; j < tmp; j++){
ret[i].page_num[j] = xmalloc(16 * sizeof(char));
ret[i].valid = 0;
}
}
return ret;
}

C Memory Management Issue

I have traced an EXC_BAD_ACCESS to the following allocation and deallocation of memory. It involves the accelerate framework in Xcode. The main issue is that this code is in a loop. If i force the loop to only iterate once then it works fine. But when it loops (7 times) it causes an error on the second iteration. Does any of this look incorrect?
EDIT: *added actual code. This segment runs if I remove certain parts and such but seems to have poor memory management which results in issues
#import <Foundation/Foundation.h>
#include <math.h>
#include <Accelerate/Accelerate.h>
for(int i = 0; i < 8; i++)
{
int XX[M][m]; //M and m are just 2 ints
for(int kk = 0; kk < M; kk++)
{
for (int kk1 = 0; kk1 < m; kk1++)
{
XX[kk][kk1] = [[x objectAtIndex: (kk + kk1 * J)] intValue]; //x is a NSMutableArray of NSNumber objects
}
}
double FreqRes = (double) freqSamp/n;
NSMutableArray *freqs = [[NSMutableArray alloc] initWithCapacity: round((freqSamp/2 - FreqRes) - 1)];
int freqSum = 0;
for(double i = -1 * freqSamp/2; i < (freqSamp/2 - FreqRes); i+= FreqRes)
{
[freqs addObject: [NSNumber numberWithInt: i]];
if(i == 0)
{
freqSum++;
}
}
int num = [x count];
int log2n = (int) log2f(num);
int nOver2 = n / 2;
FFTSetupD fftSetup = vDSP_create_fftsetupD (log2n, kFFTRadix2);
double ffx[num];
DSPDoubleSplitComplex fft_data;
fft_data.realp = malloc(nOver2 * sizeof(double)); //Error usually thrown on this line in the second iteration. Regardless of what I put there. If I add an NSLog here it throws the error on that NSLog
fft_data.imagp = malloc(nOver2 * sizeof(double));
for (int i = 0; i < n; ++i)
{
ffx[i] = [[x objectAtIndex:i] doubleValue];
}
vDSP_ctozD((DSPDoubleComplex *) ffx, 2, &fft_data, 1, nOver2);
vDSP_fft_zripD (fftSetup, &fft_data, 1, log2n, kFFTDirection_Forward);
for (int i = 0; i < nOver2; ++i)
{
fft_data.realp[i] *= 0.5;
fft_data.imagp[i] *= 0.5;
}
int temp = 1;
ffx[0] = abs(fft_data.realp[0]);
for(int i = 1; i < nOver2; i++)
ffx[i] = sqrt((fft_data.realp[i] * fft_data.realp[i]) + (fft_data.imagp[i] * fft_data.imagp[i]));
ffx[nOver2] = abs(fft_data.imagp[0]);
for(int i = nOver2-1; i > 0; i--)
{
ffx[nOver2 + temp] = sqrt((fft_data.realp[i] * fft_data.realp[i]) + (fft_data.imagp[i] * fft_data.imagp[i]));
temp++;
}
//clear Fxx and freqs data
vDSP_destroy_fftsetupD(fftSetup);
free(fft_data.imagp);
free(fft_data.realp);
[freqs release];
}
Your problem could be that you are casting malloc to a value. As you're tagging this c, I'm assuming that you are compiling in c in which case you should see this answer to a previous question as to why casting with malloc is bad:
https://stackoverflow.com/a/1565552/1515720
you can get an unpredictable runtime error when using the cast without including stdlib.h.
So the error on your side is not the cast, but forgetting to include stdlib.h. Compilers may assume that malloc is a function returning int, therefore converting the void* pointer actually returned by malloc to int and then to your your pointer type due to the explicit cast. On some platforms, int and pointers may take up different numbers of bytes, so the type conversions may lead to data corruption.
Regardless though, as the answer says, YOU SHOULD NOT BE CASTING MALLOC RETURNS, because void*'s are safely implicitly converted to whatever you are assigning it to.
As another answerer stated:
vDSP_destroy_fftsetupD(fftSetup);
Could be also free'ing the memory you allocated on accident.
Any chance the destructor of DSPDoubleSplitComplex is freeing up those two allocated blocks?
It could also be that you are only allowed to call vDSP_create_fftsetupD and vDSP_destroy_fftsetupD once during your process's lifetime

Problem with FFTW2 routine in C

I'm currently working with the FFTW2 (Fastest Fourier Transform in the West) library, and after writing a successful routine in Fortran, I am moving on to C. However, I'm having some trouble with data assigning when I try to input the data to transform (ie, the values of sin(x)). Currently, my code is:
#include <stdio.h>
#include <fftw.h>
#include <math.h>
#include <complex.h>
void compute_fft(){
int i;
const int n[8];
fftw_complex in[8];
fftwnd_plan p;
in[0]->re = 0;
in[1]->re = (sqrt(2)/2);
in[2]->re = 1;
in[3]->re = (sqrt(2)/2);
in[4]->re = 0;
in[5]->re = -(sqrt(2)/2);
in[6]->re = -1;
in[7]->re = -(sqrt(2)/2);
for(i = 0; i < 8; i++){
(in[i])->im = 0;
}
p = fftwnd_create_plan(8, n, FFTW_FORWARD, FFTW_ESIMATE | FFTW_IN_PLACE);
fftwnd_one(p, &in[0], NULL);
fftwnd_destroy_plan(p);
printf("Sin\n");
for(i = 0; i < 8; i++){
printf("%d\n", n[i]);
}
}
I've been using this http://fftw.org/fftw2_doc/ link for documentation/tutorial purposes, and currently my error is "invalid type argument of a->a (have afftw_complexa)", and the 'a' characters on either side of the -> and fftw_complex have carats above them. I'm using basically the same pattern that worked when I wrote this in Fortran, and I seem to be following the tutorial, it's really just this assignment here that I am messing up the syntax on. For the record, the compiler I am using is nvcc, if it makes a difference (I previously tried gcc). If anyone here has every used FFTW2 in C before, could you help correct my mistake? Thank you!
It might be because of your array "in" which is a array of fftw_complex so instead of using in[0]->re = 0 you should use it as in[0].re = 0. Unless fftw_complex is again typedefined to some array.
fftw_complex in[8];
in[0].re = 0;
in[1].re = (sqrt(2)/2);
in[2].re = 1;
in[3].re = (sqrt(2)/2);
in[4].re = 0;
in[5].re = -(sqrt(2)/2);
in[6].re = -1;
in[7].re = -(sqrt(2)/2);
Since ffwt_complex is an double[2] being the first dimension([0]) for the real data and the second ([1]) for the imaginary data, a safe solution is:
in[0][0] = 0;
in[1][0] = (sqrt(2)/2);
in[2][0] = 1;
in[3][0] = (sqrt(2)/2);
in[4][0] = 0;
in[5][0] = -(sqrt(2)/2);
in[6][0] = -1;
in[7][0] = -(sqrt(2)/2);
for(i = 0; i < 8; i++){
in[i][1] = 0;
}

Resources