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?
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 want to write a function that will take two integers, three times, and then return them ordered by the first integer and (for now) print them in main (though eventually I plan/hope to switch to a file-based structure to store and organize data), but I think I might have an issue with my pointers cause even when I skip concatenations (which looks like might also be another separate issue), everything Ive tried has main print a string (or no string) which never matches the input, but the print statements suggest all the looped assignments are working properly.
#include <stdio.h>
#include <string.h>
const char * entry()
{
int n;
int level;
char habit1entry[6];
char habit2entry[6];
char habit3entry[6];
for (int c = 0; c< 3; c++){
printf("Habit #\n");
scanf("%d", &n);
printf("Level:\n");
scanf("%d", &level);
switch (n)
{
case 1:;
sprintf(habit1entry, "|%d|%d|\n", n,level);
printf("n = %d\n",n);
printf("%s\n",habit1entry);
continue;
case 2:;
sprintf(habit2entry, "|%d|%d|\n", n,level);
printf("n = %d\n",n);
printf("%s\n",habit2entry);
continue;
case 3:;
sprintf(habit3entry, "|%d|%d|\n", n,level);
printf("n = %d\n",n);
printf("%s\n",habit3entry);
continue;
}
}
strcat(habit2entry,habit3entry);
printf("%s\n",habit2entry);
strcat(habit1entry,habit2entry);
printf("%s\n",habit1entry);
char *fullEntry=habit3entry;
printf("%s\n",fullEntry);
return strdup(&fullEntry[0]);
}
int main(){
const char * dataEntry = entry();
//strcpy(dataEntry,entry());
printf("Data:\n%s",dataEntry);
}
heres an example of the output(after the correct prints inside the switch cases) for an input of 3 2 1 1 2 2:
"
|2|2|
|1|1|
|2|2|
|2|2|
|��
|2|2|
|��
* stack smashing detected *: ./a.out terminated
Aborted (core dumped) "
p.s. Sorry if this all sounds silly, this is my first C project (and first real stack overflow post, plz b gentl) coming from jumping around between java, python and clojure and I would like to take an operating systems class that allows you to start without knowing C but expects you to pick it up on your own and its hard finding material that explains C concepts in a scope that matches my background knowledge and current learning constraints in terms of time available for taking deep dives through explanations that for me have ended up mostly being either hopelessly esoteric, incredibly case-specific or overly-simplistic/redundant/unhelpful explanations of programming concepts I picked up in other languages. Dont mean to complain or harp on and its probably good to get practice with different methods of asking questions and finding answers for problems like these, but the learning curve for understanding things like this (setting up the compiler/json files involved spending hours only to discover that mcafee was deleting my exes which I became convinced was a symptom of a virus, only to have the behavior stop after I restarted for a minor routine windows update and I have no idea why) outside of a traditional framework sometimes seems more like a wall and I'm worried that maybe I should revise my approach to avoid wasting too much of my time banging my head against a series of very sturdy walls. any and all advice is greatly appreciated.
Abstracting form the logic of the program, you have plenty of issues there:
You do not provide enough space for the strings
Your switch is not very related to your for loop
Names of the variables do not matter for you - but they matter for the program . Be more careful.
probably more but I forgot already
#include <stdio.h>
#include <string.h>
const char * entry()
{
int n;
int level;
char habit1entry[21] = "";
char habit2entry[14] = "";
char habit3entry[7] = "";
for (int c = 1; c < 4; c++){
printf("Habit #\n");
scanf("%d", &n);
printf("Level:\n");
scanf("%d", &level);
switch (c)
{
case 1:;
sprintf(habit1entry, "|%d|%d|\n", n,level % 10);
printf("n = %d\n",n);
printf("He1: %s\n",habit1entry);
continue;
case 2:;
sprintf(habit2entry, "|%d|%d|\n", n,level % 10);
printf("n = %d\n",n);
printf("He2 = %s\n",habit2entry);
continue;
case 3:;
sprintf(habit3entry, "|%d|%d|\n", n,level % 10);
printf("n = %d\n",n);
printf("He3 = %s\n",habit3entry);
continue;
}
}
strcat(habit2entry,habit3entry);
printf("H2 + H3 = %s\n",habit2entry);
strcat(habit1entry,habit2entry);
printf("H1 + H2 = %s\n",habit1entry);
char *fullEntry=habit1entry;
printf("FE: %s\n",fullEntry);
return strdup(fullEntry);
}
int main(){
const char * dataEntry = entry();
//strcpy(dataEntry,entry());
printf("Data:\n%s",dataEntry);
}
Welcome to the weird and wonderful world of C.
I have not actually compiled and run your program yet, just had a quick read through and though I give you my first thoughts.
The way your program is written is primed to generate stack overflows. You have three (very little) character arrays defined on the stack habitxentry, so your sprintf's will most certainly blow your stack unless both the Habit and Level inputs are less than 10. Habit is alright because your switch only allows 1, 2 or 3. Your switch does nothing if Habit is anything else.
As a side note: sprintf is not really the function to use in our security minded world. snprintf is a better choice. Not really an issue here per se as you are not passing in user supplied data but still, it's not a good habit to cultivate.
Next you strcat your character arrays together, virtually guarantying a stack violation, but lets assume this works; you are concatenating 2 and 3 into habit2entry and then 1 and 2 into habit1entry.
Next you are creating a pointer to habit3entry (not habit1entry) and returning a duplicate.
By doing so you are allocating heap in a mildy obscure manner. The callee will be responsible for freeing this memory.
I always preferred to explicitly malloc the memory and then strcpy (or memcpy) the data in.
Now when you grep your code, you only have to look for malloc.
Also, someone using the function will notice the malloc, see you have returned to pointer and realize that freeing it will now be his problem.
In order to avoid these problems some programmers leave it to the caller to supply a buffer to the function. The reasoning is that a function is supposed to do one thing and one thing only. In this case you are doing two things, you allocate memory and you fill that memory.
In your switch statement I noticed that each of your case labels are followed by an empty statement.
the semicolon at the end of that line is not necessary: write "case 1:" not "case 1:;"
You also use continue at the end of each block. This is allowed but "break" is more appropriate.
In this case it will have the same effect but normally you have more statements after the switch.
Now the difference will become apparent. Continue will jump straight to the top of the loop, break will break out of the switch and continue executing there.
Hope this gives you some insight.
Good luck.
I have the following piece of C code:
#include <stdint.h>
typedef union{
uint8_t c[4];
uint16_t s[2];
uint32_t l;
}U4;
uint32_t cborder32(uint32_t l)
{
U4 mask,res;
unsigned char* p = (unsigned char*)&l;
mask.l = 0x00010203;
res.c[(uint8_t)(mask.c[0])] = (uint8_t)p[0]; // <-- this line gives C6386
res.c[(uint8_t)(mask.c[1])] = (uint8_t)p[1];
res.c[(uint8_t)(mask.c[2])] = (uint8_t)p[2];
res.c[(uint8_t)(mask.c[3])] = (uint8_t)p[3];
return res.l;
}
And it triggers a Write overrun warning when running code analysis on it. http://msdn.microsoft.com/query/dev11.query?appId=Dev11IDEF1&l=EN-US&k=k%28C6386%29&rd=true
The error is:
C6386 Write overrun Buffer overrun while writing to 'res.c': the writable size is '4' bytes, but '66052' bytes might be written.
Invalid write to 'res.c[66051]', (writable range is 0 to 3)
And I just don't understand why ... Is there anyone who can explain me why?
I'd put this down as a potential bug in the Microsoft product. It appears to be using the full value of mask.l (0x01020304 being decimal 66051) when figuring out the array index, despite the fact you clearly want mask.c[0] forced to a uint8_t value.
So the first step is to notify Microsoft. They may come back and tell you you're wrong, and hopefully give you the C++ standard section that states why what you're doing is wrong. Or they may just state the code analysis tool is "best effort only". Since it's not actually preventing you from compiling (and it's not generating errors or warnings during compilation), they could still claim VC++ is compliant.
I would hope, of course, they wouldn't take that tack since they have a lot of interest in ensuring their tools are the best around.
The second step you should take is question why you want to do what you're doing in that way in the first place. What you have seems to be a simple byte-ordering switcher based on a mask. The statement:
res.c[(uint8_t)(mask.c[0])] = (uint8_t)p[0];
is problematic anyway since (uint8_t)(mask.c[0]) may well evaluate out to something greater than 3, and you're going to write beyond the end of your union in that case.
You may think that ensuring mask has no bytes greater than 3 may prevent this but it may be that the analyser doesn't know this. In any case, there are many ways already to switch byte order, such as with the htons family of functions or, since your stuff is hard-coded anyway, just use one of:
res.c[0] = p[0]; res.c[1] = p[1]; res.c[2] = p[2]; res.c[3] = p[3];
or:
res.c[0] = p[3]; res.c[1] = p[2]; res.c[2] = p[1]; res.c[3] = p[0];
or something else, for stranger byte ordering requirements. Using this method doesn't cause any complaints from the analyser at all.
If you really want to do it with the current mask method, you can remove the analyser warning (at least in VS2013 which is what I'm using) by temporarily supressing it (for one line):
#pragma warning(suppress : 6386)
res.c[mask.c[0]] = p[0];
res.c[mask.c[1]] = p[1];
res.c[mask.c[2]] = p[2];
res.c[mask.c[3]] = p[3];
(with casts removed since the types are already correct).
I'll copy the relevant lines:
(Declarations)
typedef struct { /* per una entrada de la taula de posicion */
int f;
int c;
} pos;
pos *p_opo[9];
(in main)
for (i = 0; i < num; i++) {
p_opo[i] = (pos *) calloc(n_fil * n_col / 2, sizeof (pos));
}
Now, after only having introduced this lines, the code breaks in an arbitrary point (in a call to a given library function). I suspect I'm corrupting something with this, although I don't know what.
All I want is to have an array of variable size arrays!
PD: num is an argument of the program. I've been running it with num=1 anyway.
num should be less or equal to 9. (0..8 allocated pointers in p_opo equals 9 !)
Note that in C that you get errors in a different place in case of memory leaks, etc. The reason for this is that by changing some code, other code or data can be rearranged and this may end up in segmentation faults.
So the problem may very well be in another part of your program. Make sure you have all you warnings turned on (like the -Wall option in gcc), it may give you some clues.
If your call to calloc asks for memory of size 0 it may return NULL, and if you are making use of that memory it could be causing the segmentation fault. So if:
0 == (n_fil * n_col / 2)
or somehow
0 == sizeof (pos) /* I don't think that this is possible */
the size of the memory that you are asking for is 0, and so calloc can return NULL.
If this is not the case then I don't think that you have enough code up there for anyone to know why it is segfaulting. You should keep in mind that errors like this can go unnoticed until you add or change some code that seems to be totally unrelated to the code that has the actual error.
Seeing you casting the return of calloc makes me suspicious. Don't do that, this leads to a typical error if you forget the include for the system function.
This happes if you are on a machine with 64 bit pointers and 32 bit int.
* 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.