* UPDATE *
Here is what I found. Whenever I had that function in there it wouldn't actually make the code lock up. It would actually make the read RTC I²C function very slow to execute, but the code would still run properly, but I had to wait a really long time to get past every time I read the RTC.
So there is an alarm interrupt for the RTC and this was triggering other I²C interactions inside the ISR, so it looks like it was trying to do two I²C communications at the same time, therefore slowing down the process. I removed the functions in the ISR and it's working now. I will keep investigating.
I am having this problem when programming an STM32F103 microcontroller using IAR 5.40. I have this function that if I try to printf a local variable it causes the code to freeze at another point way before it even gets to that function in question.
What could possibly be causing this?
This is the function:
u8 GSM_Telit_ReadSms(u8 bSmsIndex)
{
char bTmpSms[3] = {0};
itoa(bSmsIndex, bTmpSms, 10); // Converts the smsindex into a string
printf("index = %s\n", bTmpSms); // This printf caused the code to get stuck in the RTC // byte read function!
GSM_Telit_RequestModem("AT+CMGR=""1", 10, "CMGR", 5, 0);
return 1;
}
I tried this as well and this does not cause the lock I experienced:
u8 GSM_Telit_ReadSms(u8 bSmsIndex)
{
char bTmpSms[3] = {0};
itoa(bSmsIndex, bTmpSms, 10);
printf("index = 2\n");
GSM_Telit_RequestModem("AT+CMGR=""1", 10, "CMGR", 5, 0);
return 1;
}
There is no optimization enabled whatsoever and the code gets stuck when trying to read a byte out of my I²C RTC, but as soon as I remove this printf("index = %s\n", bTmpSms); or use this one instead printf("index = 2\n"); then everything is happy. Any ideas?
The bSmsIndex will never be more than 30 actually and even then the lock up happens wayyyy before this function gets called.
char bTmpSms[3] only has space for "99". If your bSmsIndex is 100 or greater, you will be trying to write to memory that doesn't belong to you.
Edit after the update
I don't have a reference to itoa on my local machine, but I found this one ( http://www.cplusplus.com/reference/clibrary/cstdlib/itoa/ ). According to that reference, the destination array MUST BE LONG ENOUGH FOR ANY POSSIBLE VALUE. Check your documentation: your specific itoa might be different.
Or use sprintf, snprintf, or some function described by the Standard.
Some ideas:
If itoa() is not properly NUL-terminating the string, then the call to printf may result in the machine looking for the NUL forever.
pmg has a very good point.
Also, consider what type the first argument to itoa() is. If it's signed and you're passing in an unsigned integer, then you may be getting an unexpected minus sign in bTmpSms. Try using sprintf() instead.
The change in code is moving the rest of your code around in memory. My guess is that some other part of the code, not listed here, is bashing some random location; in the first case that location contains something critical, in the second case it does not.
These are the worst kinds of problems to track down*. Good luck.
*Maybe not the worst - it could be worse if it were a race condition between multiple threads that only manifested itself once a week. Still not my favorite kind of bug.
It seems that if I don't initialize the variable bTmpSms to something the problem occurs.
I also realized that it is not the printf that is the problem. It is the itoa function. It got me to check that even though I didn't think that was the problem, when I commented the itoa function then the whole code worked.
So I ended up doing this:
u8 GSM_Telit_ReadSms(u8 bSmsIndex)
{
char bTmpSms[4] = "aaa"; // I still need to find out why this is !!!
itoa(bSmsIndex, bTmpSms, 10); // Converts the smsindex into a string
printf("index = %s\n", bTmpSms); // This printf caused the code to get stuck in the RTC // byte read function!
GSM_Telit_RequestModem("AT+CMGR=""1", 10, "CMGR", 5, 0);
return 1;
}
This is the itoa function I got:
char itoa(int value, char* result, int base)
{
// Check that the base if valid
if (base < 2 || base > 36) {
*result = '\0';
return 0;
}
char* ptr = result, *ptr1 = result, tmp_char;
int tmp_value;
do
{
tmp_value = value;
value /= base;
*ptr++ = "zyxwvutsr
qponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
} while (value);
// Apply negative sign
if (tmp_value < 0)
*ptr++ = '-';
*ptr-- = '\0';
while(ptr1 < ptr)
{
tmp_char = *ptr;
*ptr--= *ptr1;
*ptr1++ = tmp_char;
}
return 1;
}
What's the value of bSmsIndex you're trying to print?
If it's greater than 99 then you're overrunning the bTmpSms array.
If that doesn't help, then use IAR's pretty good debugger - I'd drop into the assembly window at the point where printf() is being called and single step until things went into the weeds. That'll probably make clear what the problem is.
Or as a quick-n-dirty troubleshoot, try sizing the array to something large (maybe 8) and see what happens.
What's the value of bSmsIndex?
If more than 99 it will be three digits when converted to a string. When zero terminated, it will be four characters, but you've allocated only three to bTmpSms so the null may get overwritten and the printf will try to print whatever is after bTmpSms until the next null. That could access anything, really.
Try to disassemble this area with index = 2 vs. index = %s.
Related
so i was going to run a function in an infinite loop which takes a number input, but then I remembered I codn't do
while (true) {
myfunc(scanf("%d));
}
because I need to put the scanf input into a variable. I can't do scanf(%*d) because that doesn't return value at all. I don't want to have to do
int temp;
while (true) {
scanf("%d", &temp);
myfunc(temp);
or include more libraries. Is there any standard single function like gets (I cod do myfunc((int) strtol(gets(), (char**) NULL, 10)); but its kinda messy sooo yea)
srry if im asking too much or being pedantic and i shod do ^
btw unrelated question is there any way to declare a string as an int--- or even better, a single function for converting int to string? I usually use
//num is some number
char* str = (char*) malloc(12);
sprintf(str, "%d", num);
func(str);
but wodnt func(str(num)); be easier?
For starters, the return value of scanf (and similar functions) is the number of conversions that took place. That return value is also used to signify if an error occurred.
In C you must manually manage these errors.
if ((retv = scanf("%d", &n)) != 1) {
/* Something went wrong. */
}
What you seem to be looking for are conveniences found in higher-level languages. Languages & runtimes that can hide the details from you with garbage collection strategies, exception nets (try .. catch), etc. C is not that kind of language, as by today's standards it is quite a low-level language. If you want "non-messy" functions, you will have to build them up from scratch, but you will have to decide what kinds of tradeoffs you can live with.
For example, perhaps you want a simple function that just gets an int from the user. A tradeoff you could make is that it simply returns 0 on any error whatsoever, in exchange for never knowing if this was an error, or the user actually input 0.
int getint(void) {
int n;
if (scanf("%d", &n) != 1)
return 0;
return n;
}
This means that if a user makes a mistake on input, you have no way of retrying, and the program must simply roll on ahead.
This naive approach scales poorly with the fact that you must manually manage memory in C. It is up to you to free any memory you dynamically allocate.
You could certainly write a simple function like
char *itostr(int n) {
char *r = malloc(12);
if (r && sprintf(r, "%d", n) < 1) {
r[0] = '0';
r[1] = '\0';
}
return r;
}
which does the most minimal of error checking (Again, we don't know if "0" is an error, or a valid input).
The problem comes when you write something like func(itostr(51));, unless func is to be expected to free its argument (which would rule out passing non-dynamically allocated strings), you will constantly be leaking memory with this pattern.
So no there is no real "easy" way to do these things. You will have to get "messy" (handle errors, manage memory, etc.) if you want to build anything with complexity.
I am prompting the user for a card number and then applying some formula on this number but I noticed an expected change in the output as the variable's value changes during the running of the code without reassigning it
the variable 'long card' value changes.
long card = checkNumber();
const long card_to_use = card;
char card_name[0];
int cardL = (floor(log10(card)) + 1);
const int first_two_digits = card_to_use/myPow(10,cardL-2);
const int first_digit = card_to_use/myPow(10,cardL-1);
if(first_two_digits>=51 && first_two_digits<=55){
strcpy(card_name, "mastercard");
}else if (first_two_digits==37 || first_two_digits==34){
strcpy(card_name, "amex");
}else if(first_digit == 4){
strcpy(card_name, "visa");
}
the value changes when if(first_two_digits>=51 && first_two_digits<=55) is executed I don't know exactly why?
I tried to capture the value of it in const long card_to_use from the beginning but it also changed actually changed to a 19 digit number which is also surprising.
thanks for reading
p.s: I am using cs50 IDE
You've declared card_name as a zero-length char array on the stack. The strcpy() call is probably clobbering the other variables on the stack (eg. card_to_use) due to overflow.
As to how this is happening before the call to strcpy() when the debugger is claiming you're at the line with if (...), that's probably due to optimization. You can disable optimization using the -O0 compile flag on gcc and clang. Note that in this case, optimization is likely not causing the call to occur before the condition check. Some instruction corresponding to the condition check is probably executing after the call to strcpy().
I believe the problem is the definition of card_name. char card_name[0] doesn't allocate any space for the characters copied during the strcpy() step.
Try changing char card_name[0] to char card_name[30].
char card_name[0];
This array has zero space, specified by the [0]. When the program writes to the array it runs off the end, corrupting other things in the memory. Changing it to something like:
char card_name[20];
Would assign 20 char spaces in an array to work with, which looks like enough for your program.
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I'm getting a segmentation fault, which I've narrowed down to a for loop in a callback function. It's strange because the program was previously working, now it's not!
struct debuggerth_command debuggerth_protocol[] = { /*
* Note: These strings are NOT null-terminated. The
* strings are 4 bytes long for memory alignment and
* integer-cast comparisons.
*/
{ "run ", debuggerth_startprocess },
{ "stop", 0 },
{ "inp ", 0 },
{ "sig ", 0 },
{ 0, 0 }
};
And this is the code:
int debuggerth_callback (struct libwebsocket_context * context,
struct libwebsocket * wsi,
enum libwebsocket_callback_reasons reason,
void * user,
void * in,
size_t len){
switch (reason) {
case LWS_CALLBACK_RECEIVE:
if (len < 4){
/* send error */
return -1;
}
/* Getting a segmentation fault
* within this loop.
*/
// I used this break to determine where the seg fault starts
// break
int i = 0;
for (; debuggerth_protocol[i].cmd; i++)
if (cmpcmd (debuggerth_protocol[i].cmd, in)) break;
//break;
if (!debuggerth_protocol[i].cmd){
int byteswritten = sprintf
(debuggerth_message,
debuggerth_format,
debuggerth_headers[0],
debuggerth_errors [0]);
libwebsocket_write (wsi, debuggerth_message,
byteswritten,
LWS_WRITE_TEXT);
return -1;
}
break;
This is the string comparison macro:
#define cmpcmd(cmd, str) ((*(int*)(cmd)) == (*(int*)(str)))
Anyone have any ideas?
One idea: relying on the fact that your strings are exactly the size of an int is rather horrendous.
People often try to do clever things like that only to be badly bitten when the underlying assumptions change, such as moving to a platform where the int type is eight bytes.
I'd ditch that macro and rewrite it to use strcmp or strncmp (a).
There's also a couple of other things to do.
First, print out (or use a debugger to examine) all variables before attempting to use them. It may be that in is NULL.
Or maybe you attempt to call the NULL commands like stop or sig, or even if you get a command that's not in your table and you blindly call it when i is equal to 4. These particular possibilities are in code not shown, following the loop, so it's pure, though I'd like to think educated, speculation on my part.
Another possibility is that you're running on an architecture that disallows unaligned access. Some architectures are optimised for accessing on specific boundaries (such as getting 32-bit values from 32-bit aligned addresses) and will run slower if you violate that alignment.
However, some architectures won't allow unaligned access at all, instead giving something like a BUS error if you try.
Since you've now indicated in a comment that you're using ARM, that's almost certainly the case. See here for some more information.
If that's the case, it's even more reason to get rid of the tricky macro and use a more conventional solution.
(a): You may also want to investigate the term "strict aliasing" at some point since this may technically be undefined behaviour.
Given this is running on ARM, I think your problem is that it's doing an unaligned memory access, which will either fail or be quite slow. It is not exactly a seg fault. See this question for example, and as suggested there -Wcast-align will probably flag it as risky. You can turn on a software workaround but that's probably slower than just fixing it in your code.
One option would be to use memcmp which gcc may be able to compile down to something nearly as simple as a word read, in the case that it is aligned.
Another option, if performance is critical, is to unwind the loop into a case statement switching by the first byte of the command. Then just check the following characters are as expected.
I looked at some of the changes to my code, as #Jonothan Leffler suggested. This was the change I made:
struct debuggerth_command {
char * cmd;
int (*function)(struct debuggerth_session *, char * input);
};
struct debuggerth_command {
char cmd[4]; // changed this an array
int (*function)(struct debuggerth_session *, char * input);
};
So, when I initialized the structure here:
struct debuggerth_command debuggerth_protocol[] = { /*
* Note: These strings are NOT null-terminated. The
* strings are 4 bytes long for memory alignment and
* integer-cast comparisons.
*/
{ "run ", debuggerth_startprocess },
{ "stop", 0 },
{ "inp ", 0 },
{ "sig ", 0 },
{ 0, 0 } /* Zero used to be a pointer value,
* but now it's the first element in a
* 4 byte array
*/
};
Which changed the evaluation of the for loop:
int i = 0;
for (; debuggerth_protocol[i].cmd; i++)
if (cmpcmd (debuggerth_protocol[i].cmd, in)) break;
To always evaluate true, because cmd is now a valid pointer to a 4-byte array - of which, the first value is 0.
I'll remove the macro, since it might not perform well on some architectures. But, couldn't this be fixed with the use of C11's alignas feature?
I'm running into a downright bizarre issue with sprintf in C that seems beyond my basic abilities to debug. Basically, I'm using a simple unit test framework (CuTest) to add some tests to an ugly (undocumented, no unit tests) code base. I added a new type of unit test, which basically duplicates the ones that are already present- but for the 64 bit integers used in the code.
This test works in general (correctly evaluates equality comparisons), but when it fails it does not produce the correct error message due to the sprintf issue. The function looks like this:
/* Comparison Function for U64 Numbers */
void CuAssertU64Equals_LineMsg(CuTest* tc, const char* file, int line, const char* message, u64 expected, u64 actual) {
char buf[STRING_MAX];
if (expected == actual) return;
sprintf(buf, "expected <%lld> but was <%lld>", expected, actual);
CuFail_Line(tc, file, line, message, buf);
}
(Note: STRING_MAX is 512, so it should be plenty large).
(Note 2: On the Cygwin system I'm currently working with, a u64 is a "long long int" variable)
When this tests fails, the error message produced is the weird part. Regardless of what the value of "actual" is, it prints 0 in that spot. So given expected = 1 and actual = 2, the message would be:
"expected <1> but was <0>"
If you switch the positions of the arguments, and make it state something like:
sprintf(buf, "actually <%lld> but expected <%lld>", actual, expected);
You'd get the output:
"actually <2> but expected <0>"
Needless to say, this makes very little sense and seems to indicate some sort of weird stack error maybe? To be quite honest, I am just entirely unclear on how such an error could occur- even in principle. I made a small working example with the CuTest code and it worked properly (did not set the second one to zero). This indicates that the neither CuTest, nor the function itself is the issue.
However, when used with the actual code base it encounters this issue. Something related to the environment (stack, memory, or variables) is the issue.
Does anyone have a clue as to why this would happen? My current candidate theories are:
1. Underflow/overflow in the sprintf function when trying to read the data. I'm not sure how this would occur though, since any data passed into the function is by value. Moreover, the data itself clearly exists- I can see each value if I switch the order.
I'm using the incorrect formatting somehow. I was pretty sure lld was correct for a long long int (and works in my minimal working example) but maybe it's fragile.
Full on stack corruption of some sort. Sure hope its not this, because I'm only on this project 20 hours a week. I doubt I could debug the whole code base to figure out something of this magnitude.
I'm currently compiling using gcc-3 in a cygwin environment, for what it's worth. Any guesses would be great, I know it's basically impossible to diagnose it specifically without seeing the whole code base, but even some leads about debugging this sort of issue would be great.
Try "%I64d" as a format string instead. I'm not certain of Cygwin but I know MinGW links in the printf function from Visual Studio's standard library, causing all sorts of havoc. Beware of any new C99 features and types such as long doubles or size_t formats.
For what it's worth here's a replacement for printf in this context:
static char *CuPrintU64(char* buffer, u64 value) {
do
*--buffer = value % 10 + '0';
while(value /= 10);
return buffer;
}
/* Comparison Function for U64 Numbers */
void CuAssertU64Equals_LineMsg(CuTest* tc, const char* file, int line, const char* message, u64 expected, u64 actual) {
static const char first[] = "expected ";
static const char second[] = " but was ";
char buf[STRING_MAX], *ptr = &buf[sizeof buf];
if(expected == actual) return;
/* sprintf(buf, "expected <%llu> but was <%llu>", expected, actual); */
*--ptr = '\0';
ptr = CuPrintU64(ptr, actual);
ptr = memcpy(ptr - second, sizeof second - 1);
ptr = CuPrintU64(ptr, expected);
ptr = memcpy(ptr - first, sizeof first - 1);
CuFail_Line(tc, file, line, message, ptr);
}
I might've gone crazy here, but I keep recompiling the exact same code, and get different answers. I'm not using any random values at all. I am strictly staying to floats and 1D arrays (I want to port this to CUDA eventually).
Is it possible on the compiler side that my same code is being redone in a way that makes it not work at all?
I run the .exe by just clicking on it and it runs fine, but when I click "compile and run" (Dev C++ 4.9.9.2) none of my images come out right. ...although sometimes they do.
...any insight on how I fix this? If I can provide any more help please tell me.
Much Appreciated.
Edit:
Here's the block of code that if I comment it out, everything runs sort of right. (Its completely deterministic if I comment this block out)
-this is a electromagnetic simulator, if that helps at all:
//***********************************************************************
// Update HZ in PML regions (hzx,hzy)
//***********************************************************************
boundaryIndex = 0;
for (regionIndex = 1; regionIndex < NUMBEROFREGIONS; regionIndex++) {
xStart = regionData[regionIndex].xStart;
xStop = regionData[regionIndex].xStop ;
yStart = regionData[regionIndex].yStart;
yStop = regionData[regionIndex].yStop ;
for (i = xStart; i < xStop; i++) {
for (j = yStart; j < yStop; j++) {
hzx = hz[i*xSize+j] - hzy[boundaryIndex]; // extract hzx
hzx = dahz[i*xSize+j] * hzx + dbhz[i*xSize+j] * ( ey[i*(xSize+1)+j] - ey[(i+1)*(xSize+1)+j] ); // dahz,dbhz holds dahzx,dbhzx
hzy[boundaryIndex] = dahzy[boundaryIndex] * hzy[boundaryIndex] + dbhzy[boundaryIndex] * ( ex[i*ySize+j+1] - ex[i*ySize+j] );
hz[i*xSize+j] = hzx + hzy[boundaryIndex]; // update hz
boundaryIndex++;
} //jForLoop /
} //iForLoop /
} //
where, NUMBEROFREGIONS is constant (8), Xsize is defined at compile time (128 here).
Well some code examples would help! But this is a classic symptom of un-initialized variables.
You are not setting some important variables (indexes to 0, switches to True etc.) so your program picks up whichever values are hanging around in memory each time you run.
As these are effectively random values you get different results each time.
Is there an indexing error with your simulated two-dimensional array? Is ey supposed to be xSize or xSize+1 wide?
dahz[i*xSize+j] * hzx +
dbhz[i*xSize+j] * ( ey[i*(xSize+1)+j] -
ey[(i+1)*(xSize+1)+j] );
Your index treats 2D array ey as being xSize+1 wide. The code for array ex treats it as being ySize wide.
dbhzy[boundaryIndex] * ( ex[i*ySize+j+1] - ex[i*ySize+j] );
You are potentially invoking undefined behaviour. There are a number of things that are undefined by the C language standard. Some of these cases can be caught by the compiler and you may be issued a diagnostic, others are harder for the compiler to catch. Here is just a few things that have undefined behaviour:
Trying to use the value of an uninitialised variable:
int i;
printf("%d\n", i); // could be anything!
An object is modified more than once between sequence points:
int i = 4;
i = (i += ++i); // Woah, Nelly!
Reading or writing past the end of an allocated memory block:
int *ints = malloc(100 * sizeof (int));
ints[200] = 0; // Oops...
Using printf et. al but providing the wrong format specifiers:
int i = 4;
printf("%llu\n", i);
Converting a value to a signed integer type but the type cannot represent the value (some say this is implementation defined and the C language specification seems ambiguous):
signed short i;
i = 100.0 * 100.0 * 100.0 * 100.0; // probably won't fit
Edit:
Answered before OP provided code.
Are you compiling it in debug mode or release mode? Each one of these have different way how they initialize the heap and memory.
As everybody said without some code of what is wrong we can't help you a lot.
My best gest from what you just explained is that your creating pointers on non allocated memory.
something like this
APointer *aFunction(){
YourData yd = something;//local variable creation
return yd;
}
main(){
APointer *p = aFunction();
}
Here p is a pointer to something that was a local varaible in aFunction and got destroyed as soon as it left the function, this will sometime by PURE LUCK still point to the right data that hasn't been written over, but this memory space will eventual be changed and your pointer will be reading something different completly random.