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 am working on a project in which I need to read CSV lines from a text file into my program. I was given a code skeleton, and asked to fill in functionality. I have a struct containing a variable for each type of value I am going to receive, but my char array is causing segmentation faults.
Here is an excerpt of my code.
None of the exerpt is part of the given code, this is all mine:
My error is a Segmentation Fault(Core Dumped), due to the code within the get timestamp space.
my test file contained only one line,
5, 10:00:10, 1, 997
/*
* YOUR CODE GOES HERE:
* (1) Read an input csv line from stdin
* (2) Parse csv line into appropriate fields
* (3) Take action based on input type:
* - Check-in or check-out a patient with a given ID
* - Add a new health data type for a given patient
* - Store health data in patient record or print if requested
* (4) Continue (1)-(3) until EOF
*/
/* A new struct to hold all of the values from the csv file */
typedef struct {
int iD;
char *time[MAXTIME + 1];
int value;
int type;
}csv_input;
/* Declare an instance of the struct, and assign pointers for its values */
csv_input aLine;
int *idptr;
char timeval[MAXTIME + 1];
int *valueptr;
int *typeptr;
/*Note: because the time char is already a pointer, I did not make another one for it but instead dereferenced the pointer I was given */
idptr = &aLine.iD;
int j; /* iterator variable */
for(j; j < MAXTIME; j++){
*aLine.time[j] = timeval[j];
}
valueptr = &aLine.value;
typeptr = &aLine.type;
/* Get the Patient ID */
*idptr = getchar();
printf("%c", aLine.iD); /* a test to see if my pointers worked and the correct value was read */
/*Skip the first comma */
int next;
next = getchar();
/* get the timestamp */
int i;
for(i = 0; i < MAXTIME; i++)
{
while ((next = getchar()) != ',')
{
timeval[i] = next;
//printf("%s", aLine.time[i]);
}
}
First:
int j; /* iterator variable */
for(j; j < MAXTIME; j++){
You need to set j to some value, j=0 makes sense. Without this you're accessing an array with an uninitialized value and you're going to get UB with that.
Second:
/*Note: because the time char is already a pointer,
No, time is an array of pointers to characters, there is a difference there.
This line:
*aLine.time[j] = timeval[j];
won't work because, for one thing, of your statement but instead dereference the pointer I was given is making an incorrect assumption. Yes, you were given an array of pointers, but they don't point to anything, they are uninitialized and as such you can't deference them until you initialize them to a valid non-NULL value.
I think you were trying to do something like this:
aLine.time[j] = &timeval; //set the pointer to the local static array
but that's only going to work in the local function scope. It'd be better if you malloc to your array of pointers.
char *time[MAXTIME + 1];
this is an array of pointers (pointer to char array) and not an array of chars
The crash come from this line
*aLine.time[j] = timeval[j];
Because as I said aLine.time[j] is a pointer and you have not allocated memory for this pointer before filling its content
Related
So I am making a game board for battle ship, but I am trying to use a struct to make it. Currently I am getting an error when trying to create the game board. I'm trying to make it this way so that when the user inputs coordinates for the ships, or when they are making a move I can easily change symbols and get to the correct coordinate on the array. This is what I am working with right now. I am using 3 file format, so I put all the parts down below.
I could create the board without using a struct, but I'm pretty sure I need to create it this way so that I am able to manipulate the board later.
If this helps this is my current error: Run-Time Check Failure #3 - The variable 'person' is being used without being initialized.
This is in the header file
typedef struct game_board
{
int board[10][10];
int row;
int col;
char symbol;
}Game_Board;
Game_Board initalize_game_board(Game_Board player);
The function
Game_Board initalize_game_board(Game_Board player)
{
int row_index = 0, col_index = 0;
printf(" 0 1 2 3 4 5 6 7 8 9\n");
for (row_index = 0; row_index < player.row; row_index++)
{
printf("%d ", row_index);
for (col_index = 0; col_index < player.col; col_index++)
{
player.board[row_index][col_index] = player.symbol;
printf("%c ", player.board[row_index][col_index]);
}
printf("\n");
}
}
In the main function
int main(void)
{
FILE *outfile = NULL;
outfile = fopen("battleship.log", "w");
Game_Board person, computer;
int who_goes_first = 0;
strcpy(person.symbol, '~');
person.row = 10;
person.col = 10;
strcpy(computer.symbol, '~');
computer.row = 10;
computer.col = 10;
welcome_screen(outfile);
printf("Player 1\n");
initalize_game_board(person);
You need return statements for both functions. Ending paren for main().
Highly recommend
computer.symbol = '~';
Instead of
strcpy(computer.symbol, '~');
Building on Ryan's answer, strcpy() assumes the source string has a null terminator, to know how many characters are to be copied. In your case, there is no null terminator in the source string. strcpy() will not stop copying till a null character is read from memory. Since you are using a single character, a simple assignment statement will do!
Also, in function initalize_game_board(), consider passing the pointer to the Game_Board structure, instead of the structure itself. When you do this, you can change the contents of the actual structure (struct 'person' in this case), by using the arrow (->) operator, within the function itself. Then you will not have to return the structure from this function. With your current design, you are creating a temporary copy of the structure, then populating it, and then (probably after modifications!) returning that structure, which will again be copied to the structure 'person'.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
When I try to run the following logic snippits, I get segmentation faults, why? Sometimes I don't get segmentation faults but instead I get odd output that does not make sense...
1. Changing a string's character
char *str = "Hello!";
str[0] = 'h'; // SIGSEGV
2. Modifying the value of a pointer
int *num_ptr;
*num_ptr = 6; // SIGSEGV
3. Using an array or pointer returned from a function
int *getPoint()
{
int cords[2] = {10, 20};
return cords;
}
/* ... */
int *point = getPoint();
int total = point[0] + point[1]; // SIGSEGV (or sometimes total = 0?)
4. Looping through n-sized array in function
void print_loop(int *array)
{
for(int i = 0; i < sizeof(array); i++)
printf("array[%d] = %d\n", i, array[i]); // SIGSEGV
}
/* ... */
int nums[3] = {1, 2, 3};
print_loop(nums);
What do I do to fix each of these and understand why they happen?
char *str;
int *num_ptr;
int *point;
^^ this code just creates a variable for you to then use which is a pointer to memory. Realize it never allocates or reserves memory.
so for 2 where you do *num_ptr = 6; you are trying to put the value of 6 into memory pointed to by num_ptr. But num_ptr does not point anywhere yet, it either points to NULL or is uninitialized and contains some random number value. If it contains some random number value odds are it is not valid memory location, hence the segmentation violation. And if it were NOT to result in a SIGSEV and the code ran then it would be by chance you got lucky; you would never want to program this way having basic concepts of programming happen by chance.
Same principle applies for all your other examples. It doesn't matter the data type. It's the basic problem of having a pointer to memory, and whether or not you have (by whatever means) reserved or allocated some valid range of storage space (RAM, disk, wherever).
str[0] = 'h'; is the same thing as *str = 'h';
str[1] = 'h'; would be the equivalent of *(str+1) = 'h';
str[2] is *(str+2)
and so on,
where str is a pointer to the starting location of a range of memory,
then because str is of data type CHAR, +1 moves 1 byte, +2 moves 2 byte.
If it were of type INT where int is 4 bytes, then +1 would be the
initial memory location + 4.
Using an array or pointer returned from a function
This doesnt't work, because you create a pointer and reserve a memory area inside a function, without malloc. When this function ends, you lose this reserved area.
So, you can't make a function that returns a pointer this way. Read a little about malloc() function.
Looping through n-sized array in function
This isn't the right way to loop through a n-sized array, sizeof return the number of bytes that you need tho allocate that structure, not how many elements you have in the array. A suggestion is by as a parameter how many elements you have, if it is a string, you can use strlen, from string.h.
these are common pit falls when someone tries migrate to C from a virtual language such as Java, C#, Python, or JavaScript. The problem is that they do not understand the concept of memory management because virtual languages take care of that now. Hopefully new programmers wanting to learn C can be directed to this answer and avoid these pitfalls -- and ultimately prevent these types of questions from filling the front page of c every day. I am going to be short worded as possible, as I know that 90% of you have already looked at this paragraph and said "lol tl;dr".
What is a Segmentation Fault (seg fault)
It's when you try to access memory that's not yours. Or you try to write to memory that is read only -- The operating system is the one responsible for enforcing this.
An analogy: address in memory are like house address on the streets. And the things inside the houses would be the data itself. If you own a house, you go to its address and add and remove furniture as you please. If you don't own the house, you're simply breaking an entry and the police (The OS) arrest you (seg fault).
Common ways to get it
P1. Changing a string's character
char *str = "Hello!";
str[0] = 'h'; // SIGSEGV
Problem: a string literal (declared within quotes, "LIKE SO") may not be modified. Attempting to do so causes undefined behavior.
Solution: allocate your string in an array.
char str[] = "Hello!";
str[0] = 'h';
P2. Modifying the value of a pointer
int *num_ptr;
*num_ptr = 6; // SIGSEGV
Problem: num is pointer, but its address has not been defined. You can't derreference a pointer unless you give it a valid address.
Solution: Make sure you point your pointers®.
int *num_ptr;
int num;
num_ptr = # // num_ptr equals the address of num
*num_ptr = 6;
P3. Using an array or pointer returned from a function
int *getPoint()
{
int cords[2] = {10, 20};
return cords;
}
/* ... */
int *point = getPoint();
int total = point[0] + point[1]; // SIGSEGV (or sometimes total = 0?)
Problem: cords is an array with automatic storage inside the function getPoint(). When this function returns, the array no longer exists, which means that point now points to invalid memory.
Solution #1: allocate coords with dynamic memory using, for example, malloc(). Dynamic memory exists as long as your program is running, or until you release it with free().
int *getPoint()
{
int *cords = malloc(2 * sizeof(int)); // get 2 ints on permanent (heap) memory
cords[0] = 10;
cords[1] = 20;
return cords;
}
/* ... */
int *point = getPoint();
int total = point[0] + point[1];
free(point); // manual destroy
Solution #2: declare the array outside the function and pass its address to getPoint(). Now instead of returning the array, it receives and modifies it.
int *getPoint(int *cords)
{
cords[0] = 10;
cords[1] = 20;
return cords;
}
/* ... */
int cords[2];
int *point = getPoint(chords);
int total = point[0] + point[1]
P4. Looping through n-sized array in function
void print_loop(int *array)
{
for(int i = 0; i < sizeof(array); i++)
printf("array[%d] = %d\n", i, array[i]); // SIGSEGV
}
/* ... */
int nums[3] = {1, 2, 3};
print_loop(nums);
Problem: In C, there is nothing holding your hand. This means you have to keep track of your own damn array lengths.
Solution: Whenever you pass an array into a function, you MUST also pass the size of the array.
void print_loop(int *array, int array_len)
{
for(int i = 0; i < array_len; i++)
printf("array[%d] = %d\n", i, array[i]);
}
/* ... */
int nums[3] = {1, 2, 3};
print_loop(nums, 3);
"My program does not have a seg fault and/or but it gives a strange result"
Seg faults and things that should cause seg faults are known as "undefined behavior". This means that the error will be different based on what compiler is used, what OS, what CPU, ect. Some cases there will not be an error at all, however that does not mean its OK. It's like saying "If OJ can get away with it then so can I" and then being surprised by the results.
**Issue overview **
The current issue i have is that i have an array which has the size of a variable which happens to be the amount of lines in a file. This is an integer which is calculated and returned, which becomes the arraysize (e.g. file text.txt has 12 lines so the array is of size 12).
I want to know how i can return this value to another c file for use in a function so i can loop through the complete array.
points to note
I am not allowed any globals at all in this assignment, no global arrays/variables at all.
The line counting functions works correctly so i will not be posting it here
The array is set up correctly and print the correct results
Most of the code from the functions has been removed to make it easier to read.
The correct #includes for each file are present, i just need an example of how to do it.
The code:
void read_from_file() {
/* reading and parsing removed */
no_of_lines = (count_lines(locof) - 1);
/* locof is a char array storing the file name */
ship ships[no_of_lines];
/* i want to return the value of no_of_lines *?
I want to return the value of no_of_lines
The c file where i need the value
/*This is where i need the variable */
void asign_mayday_to_ships() {
int* ship_arr_length = SIZE OF SHIP ARRAY NEEDED
mayday_call* mday_ptr;
ship* ship_ptr; /* this is a ship array */
mday_ptr = read_mayday_file();
ship_ptr = read_ship_locations();
int i;
for(i = 0; i < SIZE OF SHIP ARRAY; i++){
}
Just pass both pointer and size, it'a a C way.
void read_from_file() {
/* reading and parsing removed */
no_of_lines = (count_lines(locof) - 1);
/* locof is a char array storing the file name */
ship ships[no_of_lines];
some_fun_from_second_file(ships, no_of_lines);
Who calls the two fnctions? Can't you just return the nr of lines in an upper function then pass it in the second one? If not, then you must somehow store it in a variable(or a struct member) and then you can grab it later. This is a contextual solution, it might not work for you.
i had to first malloc my ships array, then set the size of the malloc depending on the amount of elements then i can return the size of the pointer:
ship* ships;
ships = malloc(sizeof (ship) * no_of_lines);
the in the function i was having trouble with:
mayday_call* mday_ptr;
ship* ship_ptr;
mday_ptr = read_mayday_file();
ship_ptr = read_ship_locations();
int arr_size = sizeof (ship_ptr) ;
int i;
for(i =0; i < arr_size; i++) {
//do something
}
`
sounds like your 'teacher' wants make you use a sentinel value. Ie put an object at the end of the array that cannot exist (a ship with name all spaces for example) then in the array processing you keep looping till you hit the magic value.
This is a bad design, but if you aren't allow globals and you aren't allow parameters I cant see what else to do
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 10 years ago.
(C) realloc array modifies data pointed by items
Hello,
A nice weird bug I feel like sharing ;-) Requires some preliminary explanations:
First, I have a type of strings PString which hold their size (and a hash value), followed by a flexible array member with the bytes. Here is the type and kind of constructor (the printfl statement at the end is debug):
typedef struct {
size_t size;
uint hash;
char bytes[];
} PString;
// offset from start of pstring struct to start of data bytes:
static const size_t PSTRING_OFFSET = sizeof(size_t) + sizeof(uint);
PString * pstring_struct (string str, size_t size, uint hash) {
// memory zone
char *mem = malloc(PSTRING_OFFSET + size * sizeof(char));
check_mem(mem);
// string data bytes:
memcpy(mem + PSTRING_OFFSET, str, size);
mem[PSTRING_OFFSET + size] = NUL;
// pstring struct:
PString * pstr = (PString *) mem;
pstr->size = size;
pstr->hash = hash;
printfl("*** str:'%s' (%u) --> pstr:'%s' (%u) 0x%X",
str, size, pstr->bytes, pstr->size, pstr); ///////////////////////
return pstr;
}
[Any comment on this construction welcome: I'm not sure at all to do things right, here. It's the first time I use flexible array members, and I could not find exemples of using them in allocated structs.]
Second, those pstrings are stored in a string pool, meaning a set implemented as hash table. As usual, "buckets" for collisions (after hash & modulo) are plain linked lists of cells, each holding a pstring pointer and a pointer to next cell. The only special detail is that the cells themselves are stored in an array, instead of beeing allocated anywhere on the heap [1]. Hope the picture is clear. Here is the definition of Cell:
typedef struct SCell {
PString * pstr;
struct SCell * next;
} Cell;
All seemed to work fine, including a battery of tests of the pool itself. Now, when testing a pstring routine (search), I noticed a string changed. After some research, I finally guessed the problem is related to pool growing, and endly could reduce the issue exactly around the growing of the array of cells (so, well before redistributing cells into lists). Here is the lines of debug prints around this growing, with copy of the show_pool routine producing the output (just shows the strings), and the output itself:
static void pool_grow (StringPool * pool, uint n_new) {
...
// Grow arrays:
show_pool(pool); /////////////////////
pool->cells = realloc(pool->cells, pool->n_cells * sizeof(Cell));
check_mem(pool->cells);
show_pool(pool); ////////////////////
...
static void show_pool (StringPool * pool) {
if (pool->n == 0) {
printfl("{}");
return;
}
printf("pool : {\"%s\"", pool->cells[0].pstr->bytes);
PString * pstr;
uint i;
for (i = 1; i < pool->n; i++) {
pstr = pool->cells[i].pstr;
printf(", \"%s\"", pstr->bytes);
}
printl("}");
}
// output:
pool : {"", "abc", "b", "abcXXXabcXXX"}
pool : {"", "abc", "b", "abcXXXabcXXXI"}
As you can see, the last string stored has an additional byte 'I'. Since in the meanwhile I'm just calling realloc, I find myself a bit blocked for further debugging; and thinking hard does not help in throwing light on this mystery. (Note that cells just hold pstring pointers, so how can growing the array of cells alter the string bytes?) Also, I'm bluffed by the fact there seems to be a quite convenient NUL just after the mysterious 'I', since printf halts there.
Thank you.
Can you help?
[1] There is no special reason for doing that here, with a string pool. I usually do that to get for free an ordered set or map, and in addition locality of reference. (The only overhead is that the array of cells must grow in addition to the array of buckets, but one can reduce the number of growings by predimensioning.)
Since size doesn't include the null terminator,
mem[PSTRING_OFFSET + size] = NUL;
is invalid. Every other issue stems from this.
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 10 years ago.
I am trying to read in a struct from a file and then display (and sort) and array. I am having trouble though which I think is to do with me not accessing the correct memory. When I print the array it comes up as loads of random numbers.
struct details
{
int numberOfPresents;
int numberOfBuildings;
int buildings[];
};
void print_int_array(const int *array)
{
for(int i=0; i<200; i++)
printf("%d | ", array[i]);
putchar('\n');
}
void sort(int buildings[], int count)
{
int i, j, temp;
do {
j = 0;
for (i = 0;i<count-1;i++)
{
if (buildings[i] < buildings[i+1])
{
j = 1;
temp = buildings[i];
buildings[i] = buildings[i+1];
buildings[i+1] = temp;
}
}
} while (j == 1);
}
int main()
{
FILE *fp;
fp = fopen("buildings.out", "r");
struct details data1;
size_t structSize = sizeof(struct details);
//size_t arraySize = sizeof(int)*sizeof(buildings);
fread(&data1, structSize, 1, fp);
for(int i=0; i<200; i++)
printf("%d | ", data1.buildings[i]);
//sort(data1.buildings );
//print_int_array(data1.buildings, arraySize);
//printf("Number of Houses: %d\n",numberOfHouses(data1.numberOfPresents, data1.buildings));
fclose(fp);
return 0;
}
The sizeof your struct only includes a minimal allocation for the array (one entry, I think). It doesn't actually allocate enough for the 200 entries you want. There are a few possible fixes.
If it will always be 200 entries, then just declare buildings as having size 200. This is the easiest.
If you know the number of entries prior to reading it, then you can do something unpleasant like (s is the number of entries):
struct details *data1 = (struct details *) malloc(sizeof(struct details)+s*sizeof(int));
and free data1 when you are done. This type of code is generally frowned upon but used to be quite common. The read command gets complicated as well.
The final option would be to change buildings to an int* and then malloc that array before reading. Again, the read would have to be done in a loop.
You've got two issues working against you printing the data.
Enough room is not allocated for the records.
Enough data is not read for the records.
The line struct details data1 only allocates enough room on the stack for one copy of the struct. You need enough for 200 of them. I'd immediately suggest an array.
struct details data1[200];
When you perform the read, fread(&data1, structSize, 1, fp), you're only reading in one record of size structSize. Now that you have enough memory allocated to read in 200 records, you can bump up the number of records you're reading to 200 as well.
fread(data1, structSize, 200, fp);
(Notice we dropped the & because we're dealing with an array now. Arrays automatically return their base address if you just reference them by name.)
Now, what if your file doesn't have 200 records in it? You probably need to capture the return value of fread() to determine how many records you actually read.
int intNumberOfRecords = fread(&data1, structSize, 200, fp);
for(int i=0; i<intNumberOfRecords ; i++)
[...]
Now that we have that working, we can look a little closer at the srtuct itself. We've got a challenge with the definition that we can't easily overcome.
struct details{
int numberOfPresents;
int numberOfBuildings;
int buildings[];
};
The last member, buildings[], is not going to read correctly from a file. This is because it's only a 32-bit integer at best in a 32-bit memory model. In other words, what you'll be reading from the disk is just a 32-bit number that points to somewhere in memory. What you won't end up with is an array that contains the buildings. If you try to access it (i.e. in your sort routine) you'll more than likely seg-fault and your program will never work. Trying to post a general solution for this is a little out of the scope of my answer. Suffice it to say, you'll either have to go with a fixed size array or dynamically write variable size arrays to disk (variable length records). The fixed size array would be a lot easier. If we change your definition to the following, we'd load up some data from the disk.
struct details{
int numberOfPresents;
int numberOfBuildings;
int buildings[16];
};
We'd also avoid seg-faulting, which is a nice plus. However, I don't know what your input file looks like so I don't know if this will work given your data.