char getType()
{
typedef struct typelookup { const char *opcodebits; char instype; } typelookup;
typelookup table[] = {
{"000000",'r'},
{"000010",'j'},
{"000011",'j'},
{ NULL }
};
for (typelookup *t = table; t->opcodebits != NULL; ++t) {
if (strcmp(t->opcodebits, opcode) == 0) {
return t->instype;
}
}
return 'i';
}
I need to be able to perform a lookup based on a string. The string is contained in a static array and if the string is in the lookup table, I want to be able to return a character which will define which type of MIPS instruction the binary refers to, hence the r, j and i as return values. This code compiles ok but when it comes to running the code I always get a "segmentation error: 11". Can anybody enlighten me as to what I'm doing wrong? Been trying to fix this error for longer than I care to admit.
What is opcode? Does the char array pointed to by opcode contain a terminating zero? If not, strcmp may keep comparing beyond the end of t->opcodebits, run out of bounds, and suddenly hit a non-readable virtual address.
I apologise for my answer sounding like a lot of additional questions. :-)
Related
The user specifies the number of lines in the output in the arguments (as the size of the page in pagination), by pressing the key he gets the next lines. How it works now:
Let's say the user chose to receive 1 row at a time:
first string
first string
second string
first string
second string
third string
struct result {
char part[32768];
int is_end_of_file;
};
struct result readLines(int count) {
int lines_readed = 0;
struct result r;
if (count == 0) {
count = -1;
}
while (count != lines_readed) {
while (1) {
char sym[1];
sym[0] = (char) fgetc(file);
if (feof(file)) {
r.is_end_of_file = 1;
return r;
}
strcat(r.part, sym);
if (*"\n" == sym[0]) {
break;
}
}
lines_readed++;
}
return r;
}
int main(int argc, char *argv[]) {
file = fopen(argv[1], "r");
while (1) {
struct result res = readLines(atoi(argv[2]));
printf("%s", res.part);
if (res.is_end_of_file) {
printf("\nEnd of file!\n");
break;
}
getc(stdin);
}
closeFile();
return 0;
}
I know that when I define a struct in the readLines function, it is already filled with previous data. Forgive me if this is a dumb question, I'm a complete newbie to C.
I'm not sure what is the question here, however I'll do my best to address what I understand. I assume the problem lies somewhere around the "previous data" you mentioned in the title and in the comments to the question.
Let's first set an example program:
#include <stdio.h>
struct result {
char part[10];
};
int main (int argc, char *argv[]) {
struct result r;
printf(r.part);
return 0;
}
The variable r has a block scope, so it has automatic storage duration. Since it has automatic storage duration, and no initializer is provided, it is initialized to an indeterminate value (as mentioned by UnholySheep and n. 1.8e9-where's-my-share m. in the comments to the question). I don't yet get all the C intricacies, but based on this, I guess you cannot rely on what the value of r will be.
Now, in the comments to the question you try to understand how is it possible that you can access some data that was not written by the current invokation of your program. I cannot tell you exactly how is that possible, but I suspect it is rather platform-specific than C-specific. Maybe the following will help you:
What is Indeterminate value?
What happens to memory after free()?
Why memory isn't zero out from malloc?
Going further, in the line
printf(r.part);
first we try to access a member part of r, and then we call printf with the value of this member. Accessing a variable of an indeterminate value results in undefined behavior, according to this. So, in general, you cannot rely also on anything that happens after invoking r.part (it doesn't mean there is no way of knowing what will happen).
There is also another problem with this code. printf's first parameter is interpreted as having the type const char *, according to man 3 printf, but there is provided a variable that has the type struct result. Indeed, there is produced the following warning when the code is compiled with gcc with the option -Wformat-security:
warning: format not a string literal and no format arguments [-Wformat-security]
Unfortunately, I don't know C well enough to tell you what precisely is happening when you do such type mismatch in a function call. But as we know that there already happened undefined behavior in the code, this seems less important.
As a side note, a correct invokation of printf could be in this case:
printf("%p", (void *)r.part);
r.part is a pointer, therefore I use the %p conversion specifier, and cast the value to (void *).
I've got a problem that seems a little odd to me.
For a quick overview:
#define LENGTH 2048
struct ShmBlock
{
int value_1;
char str[LENGTH];
}
int AssignStr(struct ShmBlock* shm, char* str)
{
if(strlen(str) > LENGTH)
return -1;
strncpy(shm->str, str, sizeof(shm->str));
return 0;
}
Code is simplified but i tried to show the lines of code that is the cause of the error. Firstly of course i establish connection to SHM, and it seems to work fine, I can assign int value with no problem, but some strange things happens when I call AssignStr(), in general, string is not copied, and every attempt to call shm->str end up with segmentation fault, second thing that surprised me was that calling AssignStr() changed my int value to some random numbers. Do you know what is the cause of this issue? And why does this error affect int value? 0.o
Most likely, when you first allocate the ShmBlock, it is zero, so when you test
if (strlen(str) > strlen(shm->str))
strlen(shm->str) is 0 (the first char in NUL), so you just return -1 without copying the string.
I have a function that looks through a number of matches from an array and find all teams in matches, that meet some conditions. When found they need to be assigned to a new array. The new array should be used as an output parameter.
I get segmentation fault: 11 when I call it. I have tried to debug but cannot seem to get why. Following is declared in main:
TEAM team_least_viewers;
double spectators = 99999;
solve_task_four(round, team, &team_least_viewers, &spectators);
And the function itself:
void solve_task_four(ROUND *round, TEAM *team, TEAM *team_least_viewers, double *spectators) {
int i, j, k = 0;
for(i=0; i<ROUNDS_PR_SEASON; i++) {
for(j=0; j<MATCH_PR_ROUND; j++) {
if(round[i].match[j].year == 2015) {
/* Searching for team name in team[]*/
for(k=0; k<NUMBER_OF_TEAMS; k++) {
/* If it matches */
if (round[i].match[j].home_team == team[k].name) {
team[k].spectators_home_last_year += round[i].match[j].spectators;
}
}
}
}
for(k=0; k<NUMBER_OF_TEAMS; k++) {
if(team[k].spectators_home_last_year < *spectators) {
*spectators = team[k].spectators_home_last_year;
}
}
}
}
The structs as requested:
typedef struct {
char weekday[WEEKDAY_SIZE], start_time[START_TIME_SIZE],
home_team[TEAM_SIZE], away_team[TEAM_SIZE];
double spectators;
int day, month, year, round, home_team_score, away_team_score;
} MATCH;
typedef struct {
MATCH match[MATCH_PR_ROUND];
} ROUND;
typedef struct {
char *name;
int points, matches_played,
matches_won, matches_draw, matches_lost,
matches_won_home, matches_won_away,
goals_for, goals_against, goal_difference;
double spectators_home_last_year;
} TEAM;
Any help is much appreciated.
I infer your questions is: How do I figure out what is causing the segmentation fault? If that's right, then one answer is to use a debugger. Another answer would be to add print statements throughout the code. The segfault is almost certainly one of the array indexings, like round[i] or round[i].match[j], so be sure to print the i and j values. You may be indexing past the end of an array or dereferencing a null pointer or an uninitialized pointer, so print the pointer values, like printf("round[%d] at %p\n", i, &round[i]).
SIGSEGV on several operating systems is signal 11, and is delivered to the process on a segmentation fault.
Segmentation faults occur when your program accesses memory in a way which isn't allowed, usually by attempting to dereference a null pointer or running off the end of an array.
In your program, the most likely culprits are are array indexes, round[i].match[j] and team[k]. (Another possibility would be if the spectator argument passed were not a valid location for writing, but this is unlikely in this particular case.) You may wish to insert code/run in a debugger to check whether each access is correct.
In particular, assuming that your ROUNDS_PR_SEASON &c. values are correct, it seems most likely that some round[i].match contains a null, if your round array was not fully initialized.
Relating to an earlier question I had about displaying the contents of specific data addresses, I'm now trying to modify the contents of individual addresses. It seems like a simple enough task, but I get a segfault every time I try. I'm using the following function:
int mem_set(Cmd *cp, char *arguments)
{
int address = 0, value = 0;
char *location;
if(sscanf(arguments, "%x %x", &address, &value) == 2)
{
location = (char*)address;
*location = value;
}
else printf("Invalid input.\n");
return 0;
}
I'm supposed to be able to change an item in a table (in this very file) from 's' to 'x' by finding its address and replacing it with the proper hex value, but I get a segfault when it gets to *location = value;. Any ideas?
Thanks!
You are assigning an integer to a pointer here
location = (char*)address;
it should be
location = (char*)&address;
you need to take the address of address isntead of it's value.
Whether this will do what you are trying to do, is something else, but this is the reason your program is invoking undefined behavior, which might lead to a SEGMENTATION FAULT.
Thanks! Works perfectly now. Java has made me stupid :(
I am having some difficulty comparing strings in C. I get correct output when I don't use my isMorse function, but when I use it the output becomes inaccurate and displays random characters. As far as I can tell, the variable "morse" is actually changed when strcmp is called on it. I am thinking that it has to do with "morse" not being a constant, but I am unsure of how to remedy it.
Thanks!!
char *EnglishToMorse(char english)
{
static char *morse;
int i;
for (i = 0; i < LOOKUP_SIZE; i++)
{
if (lookup[i].character == english)
{
morse = lookup[i].morse;
return morse;
}
}
morse = &english; // Problem was here!!!
return morse;
}
I have a little guess. The function EnglishToMorse() might be returning a pointer to memory from the stack. If so, running another function after EnglishToMorse() will alter that memory. This would be due to a mistake in EnglishToMorse() -- declaring a local array of char and returning a pointer to it.
Without seeing the code for EnglishToMorse(), this is just a stab in the dark. You could provide us more code to look at, and win.
You have a static variable in EnglishToMorse, but it's the wrong one. There's no need for morse to be static -- you simply return it. But you do need english to be static -- rather than on the stack -- since you return its address. Also, it needs to be a NUL-terminated string. Do something like
char *EnglishToMorse(char english)
{
static char save_english[2]; /* initialized to 0's */
int i;
for (i = 0; i < LOOKUP_SIZE; i++)
if (lookup[i].character == english)
return lookup[i].morse;
save_english[0] = english;
return save_english;
}
Note, however, that the caller of EnglishToMorse must use the result or save it before EnglishToMorse is called again, since the second call may overwrite static_english.
The reason your morse variable appears to change is because it points to an area on the stack. The reason it points to an area on the stack is because you assigned it the address of your parameter english, which got pushed onto the stack when you called your function then popped off the stack once the function completed.
Now your morse variable will point to whatever memory takes that same location on the stack, which will constantly change throughout the lifetime of your program.
In my opinion, the best way to fix this problem would be to return a NULL pointer from EnglishToMorse if the character is not A-Z... then check for the NULL pointer in your isMorse function. After all, it's good practice to check for NULL pointers in code.
char* EnglishToMorse(char english)
{
int i;
english = toupper(english);
for (i = 0; i < LOOKUP_SIZE; i++)
{
if (lookup[i].character == english)
return lookup[i].morse;
}
return NULL;
}
int isMorse(char* morse)
{
int i;
/* Check for NULL, so strcmp doesn't fail. */
if (morse == NULL) return 0;
for (i = 0; i < LOOKUP_SIZE; i++)
{
if(strcmp(morse, lookup[i].morse) == 0)
return 1;
}
return 0;
}
It looks like the problem is likely in this function:
char *EnglishToMorse(char english) {
static char *morse;
// ...
morse = &english;
return morse;
}
You are returning the address of a parameter (english) that's passed into the function. This parameter ceases to exist after the function returns (and before the caller gets a chance to actually see the value). It appears as though you've attempted to fix this by declaring the morse variable static, but this only makes the morse variable itself static, not whatever it points to.
Also, strings in C must be terminated with a NUL character. By returning a pointer to a single character (as in english), there is no guarantee that the next byte in memory is or is not a NUL character. So the caller, who is expecting to see a NUL-terminated string, may get more than they bargained for.
char *EnglishToMorse(char english)
and
morse = &english;
are the problem.
You should never return a pointer to a local variable or a function parameter.