I've been at this for hours with little progress made. I need to know why exactly my program is crashing when scanf() is called. The error message: "Segmentation fault; core dumped" leads me to believe that I'm not allocating memory to the dynamic array correctly. If this is the case could someone tell me how I can correctly allocate memory to add one struct to the array?
#include <stdio.h>
#include <stdlib.h>
/*
*
*/
enum Subject{
SER = 0, EGR = 1, CSE = 2, EEE = 3
};
struct Course{
enum Subject sub;
int number;
char instructor_name[1024];
int credit_hours;
}*course_collection;
int total_courses = 0;
int total_credits = 0;
void course_insert();
void resizeArray();
int main(int argc, char** argv) {
int choice = 0;
while(choice != 4){
printf("Welcome to ASU, please choose from the menu"
"choices.\n\n");
printf("_____________________________________________\n\n");
printf("Menu:\n 1.Add a class\n 2. Remove a class\n"
" 3.Show classes\n 4.Quit");
printf("\n\nTotal credit hours: %d\n\n", total_credits);
printf("\n\n_________________________________________");
scanf("%d", &choice);
if(choice == 1){
resize_array(total_courses);
course_insert();
}
else if(choice == 3)
print_courses();
}
return (EXIT_SUCCESS);
}
void resize_array(int total_courses) {
course_collection = malloc(total_courses +
sizeof(course_collection));
}
void print_courses() {
int i;
for(int i = 0; i < total_courses; i++){
printf("\nInstructor: %s\n\n",
course_collection[i].instructor_name);
}
}
void course_insert(){
printf("\n\nEnter the instructor's name\n\n");
scanf("%s" , course_collection[total_courses].instructor_name);
total_courses++;
}
//will crash just after scanf();
//must press 1 & enter for correct output
After entering a few instructor names I choose the third option from the menu and that should iterate through the array and print each instructor's name but all I get are blanks lines and the last instructor name I imputed.
UPDATE
#user3545894 I've tried this and it seems to work fine but I still get the issue with the output not being correct. I should be able to iterate through the array and print the strings in each subscript.
The problem came from malloc(total_courses + sizeof(course_collection))
You only allocate array of pointer of course_collection.
You need allocate memory for whole the struct Course
It should be malloc(total_courses * sizeof(struct Course))
User this malloc(total_courses + sizeof(struct Course)) instead of malloc(total_courses + sizeof(course_collection))
segmentation fault due to memory allocation mostly for arrays
arr[n] we use it till '0' to 'n-1' { carefully observe not 'n'}
Related
so as the question says I get a segmentation fault every time I try to enter in a name for the customer. This program does compile and works until it gets to the customer name part. I'm not sure if the problem is with malloc. Could anyone show me what I am doing wrong? I've been trying to figure this out for awhile now with no luck. Thanks
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define END_OF_STRINGS '\0'
#define NEWLINE '\n'
#define MAX_CUSTOMERS 100
#define MIN_CUSTOMERS 2
#define MAX_NAME_LENGTH 20
#define DB_ALLOC_ERR 1
#define QUIT 0
struct customer
{
char *p_last_name[MAX_NAME_LENGTH + 1];
float amount_owed;
int priority;
};
void print_instructions();
int number_of_customers();
void get_accounts(struct customer *p_customer_start, int
customer_amount);
void clean_names(struct customer *p_customer_start, int
customer_amount);
void sort_names(struct customer *p_customer_start, int
customer_amount);
void print_results(struct customer *p_customer_start, int
customer_amount);
int main()
{
struct customer *p_customer;
int customer_amount;
while (print_instructions(), (customer_amount =
number_of_customers()) != QUIT)
{
if ((p_customer = (struct customer *)malloc(sizeof(*p_customer) *
MAX_NAME_LENGTH)) == NULL)
{
printf("\nError #%d occurred in main()", DB_ALLOC_ERR);
printf("\nCannot allocate memory for database of customer ");
printf("\naccountable records");
printf("\nThe program is aborting");
exit (DB_ALLOC_ERR);
}
get_accounts (p_customer, customer_amount);
clean_names (p_customer, customer_amount);
sort_names (p_customer, customer_amount);
print_results(p_customer, customer_amount);
printf("%c", NEWLINE);
free(p_customer);
}
return 0;
}
void print_instructions()
{
printf("\n\nThis program allows you to input customers which owe");
printf("\nyou money (your accounts receivable), and manage these");
printf("\naccounts in a database. You will enter the following:");
printf("\n Customer last name (1-20 characters)");
printf("\n Amount the customer owes (to the exact cent)");
printf("\n Customer priority (1=VIP, 2=Important, 3=Regular)");
printf("\nFrom 2 to 100 customers may be processed.");
return;
}
int number_of_customers()
{
int user_choice;
printf("\n\nGet the customers for the database");
printf("\n--------------------------------------------------");
do
{
printf("\nHow many customers do you have (%d to %d, %d=quit): ", MIN_CUSTOMERS, MAX_CUSTOMERS, QUIT);
scanf ("%d", &user_choice);
} while ((user_choice < MIN_CUSTOMERS ||
user_choice > MAX_CUSTOMERS) && user_choice != QUIT);
return user_choice;
}
void get_accounts(struct customer *p_customer_start, int
customer_amount)
{
struct customer *p_customer;
for (p_customer = p_customer_start; (p_customer - p_customer_start)
< customer_amount; p_customer++)
{
printf("\nCustomer number %d", (int)(p_customer -
p_customer_start + 1));
printf("\n Enter the customer's last name: ");
scanf ("%20s", p_customer->p_last_name[MAX_NAME_LENGTH + 1]);
getchar();
do
{
*p_customer->p_last_name[MAX_NAME_LENGTH] = getchar();
p_customer->p_last_name[MAX_NAME_LENGTH]++;
} while (!NEWLINE);
p_customer->p_last_name[MAX_NAME_LENGTH + 1] = END_OF_STRINGS;
printf("\n Enter the amount owed: ");
scanf ("%f", &p_customer->amount_owed);
do
{
printf("\n Enter the customer's priority (1-3): ");
scanf ("%d", &p_customer->priority);
} while (p_customer->priority < 1 || p_customer->priority > 3);
}
return;
}
void clean_names(struct customer *p_customer_start, int
customer_amount)
{
char *p_fast = p_customer_start->p_last_name[MAX_NAME_LENGTH],
*p_slow = p_customer_start->p_last_name[MAX_NAME_LENGTH];
if (tolower(*p_fast))
*p_slow++ = toupper(*p_fast);
while (*p_fast != END_OF_STRINGS)
{
if (!isspace(*p_fast) || isalpha(*p_fast))
*p_slow++ = tolower(*p_fast);
p_fast++;
}
*p_slow = END_OF_STRINGS;
return;
}
void sort_names(struct customer *p_customer_start, int
customer_amount)
{
char *p_inner[MAX_NAME_LENGTH],
*p_outer[MAX_NAME_LENGTH],
temp[MAX_NAME_LENGTH];
for (p_outer[MAX_NAME_LENGTH] = p_customer_start ->
p_last_name[MAX_NAME_LENGTH]; (p_outer - p_customer_start ->
p_last_name)
< customer_amount; p_outer[MAX_NAME_LENGTH]++)
{
for (p_inner[MAX_NAME_LENGTH] = p_outer[MAX_NAME_LENGTH + 1];
(p_inner - p_customer_start ->
p_last_name) < customer_amount; p_inner[MAX_NAME_LENGTH]++)
{
if (strcmp(p_outer[MAX_NAME_LENGTH],
p_inner[MAX_NAME_LENGTH]))
{
temp[MAX_NAME_LENGTH] = *p_outer[MAX_NAME_LENGTH];
*p_outer[MAX_NAME_LENGTH] = *p_inner[MAX_NAME_LENGTH];
*p_inner[MAX_NAME_LENGTH] = temp[MAX_NAME_LENGTH];
}
}
}
return;
}
void print_results(struct customer *p_customer_start, int
customer_amount)
{
char last_name[MAX_NAME_LENGTH];
float amount_owed = p_customer_start->amount_owed;
printf("\n Here is the accounts receivable customer database");
printf("\n=====================================================");
printf("\n Customer Name Amount Priority");
printf("\n-------------------- --------- -------------");
printf("\n %s $ %.2f ", last_name,
amount_owed);
switch (p_customer_start->priority)
{
case 1:
printf("1 (VIP)");
break;
case 2:
printf("2 (Important)");
break;
case 3:
printf("3 (Regular)");
break;
}
printf("\n\n******* End Of Customer Database Processing *******");
return;
}
i believe a start of your problem is here:
struct customer
{
char *p_last_name[MAX_NAME_LENGTH + 1];
float amount_owed;
int priority;
};
with that code you create 21 pointers to char.
What you want is character pointer to space that will hold MAX_NAME_LENGTH + 1 characters
Therefore you would want something simply like:
struct customer
{
char last_name[MAX_NAME_LENGTH + 1];
float amount_owed;
int priority;
};
I also changed p_last_name to just last_name so to the eyes it reads more logically, but you may call it whatever you like, but to say p_last_name is to imply it's a pointer which is not needed, and it reads poorly
When declaring or defining variables, you read from right to left,
it would then be an array because of [] which is 21 big, called last name and it's an array of the char data type.
Now the thing with C is that arrays and pointers have something in common, or can often be confused... because they are technically the same thing. Any array that you define, which in turn allocates space in memory, is nothing more than a pointer to the beginning of the array, that's it!
when you do something like last_name[7] then the 7 is how many jumps from the beginning of the array, which is always known as last_name in your case. The size of the jump is solely dependent upon the data type of the array when it was defined. In your case it is char which is 1 byte, so a jump of last_name[7] would be 7 bytes away from where last_name points to.
For example if the contents in memory where `last_name` points to is abcdefghijklmnopqrst
then char last_name[MAX_NAME_LENGTH + 1]; would define a variable called last_name which is technically a character pointer to contiguous chunk of memory that is MAX_NAME_LENGTH + 1 bytes because of data type char and it is a pointer to the beginning of that chunk of memory.
*last_name is the same as last_name[0] which deferences the character pointer last_name such that it returns the contents of memory which is a
*(last_name+2) is the same as last_name[2] which is c
Also, in
int main()
{
struct customer *p_customer;
int customer_amount;
this statement struct customer *p_customer; creates one pointer called p_customer that is a pointer which will point to some chunk of memory (hasn't happened yet) that is of the data type struct customer which is defined above. Ok to there. Then at
if ((p_customer = (struct customer *)malloc(sizeof(*p_customer) *
MAX_NAME_LENGTH)) == NULL)
where you use malloc to reserve some chunk of memory for what you are doing, you are really doing sizeof( a pointer )
what you should be doing is (struct customer *) malloc( sizeof( struct customer )) in addition to correctly defining a 21 byte array of characters called last_name in struct customer.
It should read out in English logically, oftentimes from right to left, if it does not then suspect a problem. Also when compiling learn to use -W it can be your friend and alert you to problems like this.
your original code is likely not allocating or reserving a large enough chunk of memory for the number of characters you type in to store in p_last_name.
I am trying to improve my C skills so I apologize if my question is long. I am having a hard time understanding as to why my struct pointer holds the wrong value in my program, I tried to debug it but I am still relatively new to C and was hoping one of you could tell me what I'm doing wrong here and how I could improve my code and what to focus on.
I am making a program that stores user data on this struct and then prints it out.
typedef struct table {
char *firstName;
char *lastName;
int id;
}USER;
This function below stores the first name
void firstName(int *counter, int *check, USER *pt) {
for (int i = *counter; i < *check; i++) {
pt[i].firstName = calloc (MAX_LENGTH, sizeof(pt));
printf("Enter First Name: ");
getchar();
fgets(pt[i].firstName, MAX_LENGTH, stdin);
}
}
This is just my bool function returning true or false
bool isTrue(char *decision) {
if(*decision == 'Y') {
return true;
}
else {
return false;
}
}
And this is my main
int main(int argc, char **argv) {
USER *pt = calloc(1, sizeof(pt));
int counter = 0, check = 0;
char decision = '\0';
while (1) {
printf("Would you like to enter a user?(Y/N):");
fgets(&decision, 2, stdin);
strtok(&decision, "\n"); //remove the newline char
if (!isTrue(&decision)) {
break;
}
if (counter != 0) {
pt = realloc(pt, sizeof(pt) * 10); //the 10 is temporary
}
check = counter + 1; // make sure loop only runs once.
firstName(&counter, &check, pt);
++counter; // increment counter;
}
printStruct(pt, &counter);
return 0;
}
When I run it out sometimes it works fine and returns everything and sometimes it skips a value. This is what I get. It skips the value at pointer index 1 and prints garbage instead.
Would you like to enter a user?(Y/N):N
First name at array 0 is Ermir
First name at array 1 is P#1First name at array 2 is Kevin
First name at array 3 is Blaus
First name at array 4 is Adam
Also I was wondering why is it when I realloc here If i do I get a realloc error when I enter the second name.
if (counter != 0) {
pt = realloc(pt, sizeof(pt) * 10); //realloc(pt, sizeof(pt) * counter + 1) wont work
}
char decision = '\0';
...
fgets(&decision, 2, stdin);
You are only allocating 1 char but are at least reading 2 chars into it. Fix by allocating a sufficiently sized array for decision.
Unrelated but in firstName() pt[i].firstName = calloc (MAX_LENGTH, sizeof(pt)); should be pt[i].firstName = calloc (MAX_LENGTH, 1);
I prefer to create a Dictionary object and add 3 words to it.
My program has no compilation error but gets a run time error in the second for loop, is the problem in addNewWord function? Do I need pass a pointer to the DictionaryWord object ?
Please help me.
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<string.h>
typedef struct{
char* name;
char* mean;
} Words;
typedef struct{
Words* word;
int size;
} Dictionary;
Dictionary createNewDictionary();
Words createNewWord();
void addNewWord(Words newword, Dictionary dic);
Dictionary createNewDictionary(){
Dictionary dic;
dic.size = 0;
dic.word = (Words*)malloc(dic.size*sizeof(Words));
return dic;
}
Words createNewWord(){
Words newword;
newword.name = (char*)malloc(30*sizeof(char));
newword.mean = (char*)malloc(30*sizeof(char));
printf("============================\n");
printf("Enter word: ");
scanf("%[^\n]", newword.name);
fflush(stdin);
printf("\nEnter meaning: ");
scanf("%[^\n]", newword.mean);
return newword;
}
void addNewWord(Words newword, Dictionary dic){
dic.size++;
dic.word = (Words*)realloc(dic.word,dic.size*sizeof(Words));
strcpy(dic.word[dic.size-1].name, newword.name);
strcpy(dic.word[dic.size-1].mean, newword.mean);
}
int main(){
Dictionary d = createNewDictionary();
for (int i=0;i<3;i++){
addNewWord(createNewWord(), d);
}
return 0;
}
There are lots of problem with your code:
Given the longest word in English is around 30 characters, this size allocation is realistic for the word, but not for the defintion:
newword.name = (char*)malloc(30*sizeof(char));
newword.mean = (char*)malloc(30*sizeof(char));
This makes little obvious sense:
dic.size = 0;
dic.word = (Words*)malloc(dic.size*sizeof(Words));
you called malloc() on zero! You're only spared by your later realloc(). Even if intentional, it really deserves a comment.
This doesn't really work as fflush() is for output streams:
fflush(stdin);
see: How to clear input buffer in C? And whatever fix you use has to apply to both scanf() calls, not just one!
Per #Jarvis, this doesn't work:
dic.word = (Words*)realloc(dic.word,dic.size*sizeof(Words));
strcpy(dic.word[dic.size-1].name, newword.name);
strcpy(dic.word[dic.size-1].mean, newword.mean);
as you didn't allocate any space for name and mean in dic so you're copying into random memory.
Per #Jarvis, doesn't work:
void addNewWord(Words newword, Dictionary dic){
dic.size++;
dic.word = (Words*)realloc(dic.word,dic.size*sizeof(Words));
You're passing dic by value so inside addnewWord() you've a copy of dic so the original dic's size will be the same as it was before the call!
Memory leak:
addNewWord(createNewWord(), d);
you dropped your handle onto what createNewWord() returned so you can never free the memory it malloc()'d
You malloc() memory but provide no means to eventually free it.
Passing and returning structs by value is a disaster in a situation like this, as the data keeps getting copied. At the least it's inefficient, at worst its buggy like the size issue above. Rather than risk it, pretend they can only be passed and returned by pointer and you'll be playing it safe and get a better result.
Below is a rework of your code (in C) with fixes, style tweaks and an attempt at a consistent terminology. It also provides some minimal test code and the ability to free your data:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_WORD_LENGTH 30
#define MAX_DEFINITION_LENGTH 1024
typedef struct entry {
char *word;
char *definition;
} Entry;
typedef struct dictionary {
Entry *entries;
int num_entries, max_entries;
} Dictionary;
Dictionary *createNewDictionary() {
Dictionary *dictionary = malloc(sizeof(*dictionary));
dictionary->num_entries = 0;
dictionary->max_entries = 1;
dictionary->entries = calloc(dictionary->max_entries, sizeof(*dictionary->entries));
return dictionary;
}
void freeEntry(Entry *entry) {
free(entry->word);
free(entry->definition);
free(entry);
}
void freeDictionary(Dictionary *dictionary) {
for (--dictionary->num_entries; dictionary->num_entries >= 0; --dictionary->num_entries) {
// we can't call freeWord() here -- why.
free(dictionary->entries[dictionary->num_entries].word);
free(dictionary->entries[dictionary->num_entries].definition);
}
free(dictionary->entries);
free(dictionary);
}
void purgeInput() {
int c;
while ((c = getchar()) != '\n' && c != EOF) { }
}
Entry *requestNewEntry() {
Entry *entry = malloc(sizeof(*entry));
entry->word = malloc(MAX_WORD_LENGTH);
entry->definition = malloc(MAX_DEFINITION_LENGTH);
printf("============================\n");
printf("Enter word: ");
scanf("%[^\n]", entry->word);
purgeInput();
printf("\nEnter definition: ");
scanf("%[^\n]", entry->definition);
purgeInput();
return entry;
}
void addNewEntry(Entry *entry, Dictionary *dictionary) {
if (dictionary->num_entries == dictionary->max_entries) {
dictionary->max_entries *= 2;
dictionary->entries = realloc(dictionary->entries, dictionary->max_entries * sizeof(*dictionary->entries));
// check if realloc returns NULL and if so, handle the error.
}
dictionary->entries[dictionary->num_entries].word = strdup(entry->word);
dictionary->entries[dictionary->num_entries].definition = strdup(entry->definition);
dictionary->num_entries++;
}
int main() {
Dictionary *d = createNewDictionary();
for (int i = 0; i < 3; i++) {
Entry *e = requestNewEntry();
addNewEntry(e, d);
freeEntry(e);
}
printf("\nRead: ");
for (int i = 0; i < d->num_entries; i++) {
printf("%s (%lu chars) ", d->entries[i].word, strlen(d->entries[i].definition));
}
printf("\n");
freeDictionary(d);
return 0;
}
CREATING A PUN DICTIONARY
> ./a.out
============================
Enter word: silkworm
Enter definition: Two silkworms had a race but ended up in a tie.
============================
Enter word: horse
Enter definition: A horse is a stable animal.
============================
Enter word: termite
Enter definition: A termite walks into a pub and asks, "Is the bar tender here?"
Read: silkworm (47 chars) horse (27 chars) termite (62 chars)
>
I see what's wrong with your code. First of all, you need to pass your Dictionary object by pointer to the function, addNewWord, and in the function addNewWord, you again need to allocate memory to each of the char* fields, name and mean, of the dic object. Here is the corrected code :
void addNewWord(Words newword, Dictionary *dic){
dic->size++;
dic->word = (Words*)realloc(dic->word, dic->size*sizeof(Words));
dic->word[dic->size-1].name = (char*)malloc(30*sizeof(char)); //added
dic->word[dic->size-1].mean = (char*)malloc(30*sizeof(char)); //added
strcpy(dic->word[dic->size-1].name, newword.name);
strcpy(dic->word[dic->size-1].mean, newword.mean);
}
Pass the dictionary's address as :
addNewWord(createNewWord(), &d);
and change the definition as well as prototype of the function as well :
void addNewWord(Words newword, Dictionary *dic)
Find the complete code here : http://pastebin.com/ZN69hevj
I'm writing a homework program in C. The program should take records from an input file and write those record to an output file. It seems like there is something wrong with the print_to_file function. I keep getting segmentation fault 11. Please help. My code is as below.
#include <stdio.h>
#include <stdlib.h>
typedef struct car { // create a struct type Car
char *license_plate;
int parking_spot;
int num_tickets;
int time_left;
} Car;
#define LICENSEPLATELENGTH 10
Car* import_cars(char *filename, int numCars);
void print_to_file(char* filename, Car* garage, int numCars);
int main(int argc, char * argv[]) {
if(argc != 4)
printf("Incorrect input.\n");
else {
int number = atoi(argv[1]);
Car* parked_car = (Car*)malloc(sizeof(Car) * number);
parked_car = import_cars(argv[2], number);
print_to_file(argv[3], parked_car, number);
free(parked_car);
}
return 0;
}
Car* import_cars(char* filename, int numCars)
{
Car* inCar = (Car*)malloc(sizeof(Car) * numCars);
inCar->license_plate = (char*)malloc(sizeof(char) * 8);
//Question: How do I do if I the plate length is varied. How to malloc space to it?
FILE* inFilePtr;
if((inFilePtr = fopen(filename, "r")) == NULL)
printf("Error! Unable to open file %s. Check again.\n", *filename);
else
{
int i = 0;
fscanf(inFilePtr, "%s", inCar[i].license_plate);
fscanf(inFilePtr, "%d%d%d", inCar[i].parking_spot, inCar[i].num_tickets, inCar[i].time_left);
printf("%s %d %d %d \n", inCar[i].license_plate, inCar[i].parking_spot, inCar[i].num_tickets, inCar[i].time_left);
for(i = 1; i < numCars; i++)
{
fscanf(inFilePtr, "%s", inCar[i].license_plate);
fscanf(inFilePtr, "%d%d%d", inCar[i].parking_spot, inCar[i].num_tickets, inCar[i].time_left);
printf("%s %d %d %d \n", inCar[i].license_plate, inCar[i].parking_spot, inCar[i].num_tickets, inCar[i].time_left);
}
}
fclose(inFilePtr);
return(inCar);
//free(inCar.license_plate); `
//Question: Do I need to free space here would it remove the value
//stored in the variable which passed to main?
}
void print_to_file(char* filename, Car* garage, int numCars) {
FILE* outFilePtr;
if((outFilePtr = fopen(filename, "w+")) == NULL){
printf("Error! Cannot Open File %s!", *filename);
printf("here\n");
} else {
int i = 0;
for(i = 0; i < numCars; i++) {
printf("%s\n%d %d %d\n", garage[i].license_plate, garage[i].parking_spot, garage[i].num_tickets, garage[i].time_left);
fprintf(outFilePtr, "%s\n%d %d %d\n", garage[i].license_plate, garage[i].parking_spot, garage[i].num_tickets, garage[i].time_left);
}
}
fclose(outFilePtr);
}
This is my input command.
./a.out 6 garage.txt output.txt
Here is what print in my terminal.
fi590dz 20 2 25
57fjgmc 8 0 55
7dkgjgu 25 1 15
f9e829d 1 2 60
4jgfd81 12 2 10
Segmentation fault: 11
By the way, I'm pretty new in programming and really bad with debugging. Could you give me some tips of how to debug or any debugging tools? I use a mac so gdb doesn't work.
Not a complete answer, because it’s a homework problem and you want to figure it out yourself, but here are some hints.
First, you really want to learn how to run your program in a debugger and get it to tell you which line crashed the program, and on which data.
Second, make sure you initialize the pointers for every element of the array before you try to read or write them.
Third, you’ll save yourself a lot of trouble if you initialize all your dynamic and local variables to zeroes, not garbage. It will make a lot of bugs reproducible, make a lot of bugs crash immediately instead of corrupting memory, and also make it obvious when you debug that you’re using uninitialized data.
Therefore, I suggest you get in the habit of allocating your dynamic arrays with calloc(), not malloc().
The problem lies within your parked_car = import_cars(argv[2], number); and Car* import_cars(char* filename, int numCars);functions.
Indeed in Car* import_cars(char* filename, int numCars); you are doing this:
Car inCar;
inCar.license_plate = (char*)malloc(sizeof(char) * 8);
So you are creating a local variable that is not accessible outside of the function (many different things can happen to the memory after the end of the function).
So when you do: parked_car = import_cars(argv[2], number); you are assigning to parked_car a freed variable.
A solution is to simply use the parked_caras an argument of your import_cars() function. All modifications made within the function will still be valid after it returns. So you should have:
void import_cars(char* filename, int numCars, Car* car);
For everyone who met the issue here, I found the problem in my program. The problem is that I didn't allocate space for each of the license_plate pointer in the structure. So my way to solve it is add a line as below in the for loop of the import_cars function.
inCar[i].license_plate = (char*)malloc(sizeof(char) * LICENSEPLATELENGTH);
I was doing a study on a program which is working (mostly) and... I ran into a bug that causes a complete crash in the system at the finish line. After print-screening to pinpoint the leak, I'm reasonably sure I've found the gremlin in it's hiding spot, but I can't think of any bug spray solution to this!
Would any of you have ideas or advice on solving this puzzle? I think a fresh pair of eyes would do wonders! I definitely appreciate your time, I'm pretty sure it's really something simple at the end of it all! >_<
Thank you for any comment or suggestions!
Information about the program + script:
Take any number of user-input (numbers only) strings
When user inputs an empty string, the program will detect that as the end of user inputs, and proceed with wrapping things up.
tokenize and convert each token to integers.
Add the ints into dynamically allocated database.
Here are anomalies I found
Main_Size always has a final result 1 above what it should be.
The error likely stems from the loop() function I created. Normally when a user inputs an empty string, that should be the end of it. But the program seems to count that empty string and ship it off into the assembly, where a NULL value eventually gets housed into the main int-array. I'm almost 100% positive that's where my error is. I've tried multiple different ways to detecting a null string and avoid sending that to the rest of assembly, but no luck so far :(
The aggressive print-debugging I used seems to "break formation" at the final round of printing a single string. There's an additional line break, and I have no idea how it got there.
Using a scanf prompt to signal end of user-input strings yields good results, but the moment more than one string are entered before the end, the program goes haywire.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE 12
#define MIN_SIZE 2
int loop(int* Main_Array, char str[], int Main_Size);
int* Create_Main_Array();
int Input_String(char str[]);
int Token_Atoi(char str[], int numElements, int* Main_Array, int Main_Size);
int Dynamic_Fitting(int* Main_Array , int Incomming_int , int Main_Size);
void Free_All(int* Main_Array);
////////////////////
/////////////////////////////////////////////////
int main()
{
char str[MAX_SIZE];
int* Main_Array = Create_Main_Array(), Main_Size = 0;
//Main_Size = The number of elements currently in the dynamic memory.
//This number should increase by 1 for every new int you add into the
//array, starting from zero, as in Main_Array[0] = ####
Main_Size = loop(Main_Array, str, Main_Size);
printf("\n\nMain_Size final size is: %i\n", Main_Size);
for(int i=0; i<Main_Size; i++)
printf("Check: %i \n", Main_Array[i]);
Free_All(Main_Array);
system("PAUSE");
return 0;
}
/////////////////////////////////////////////////
//Sets up Dynamic Space. It will be realloced in the future.
/////////////////////////////////////////////////
int* Create_Main_Array()
{
return (int*)malloc(MAX_SIZE*sizeof(int));
}
/////////////////////////////////////////////////
//Calls up the user to input a string.
//Loops the entire process so long as returned string is larger then 0.
//Returns total Element size of Main, after it's been modified in the program.
/////////////////////////////////////////////////
int loop(int* Main_Array, char str[], int Main_Size)
{
int numElements;
while(numElements>0)
{
numElements = Input_String(str);
//for some reason, at the very end of the loop, it will tag on another '\0'
//into the Main_Array, which causes a crash. Likely the setup at line 52.
Main_Size = Token_Atoi(str, numElements, Main_Array, Main_Size);
}
return Main_Size;
}
/////////////////////////////////////////////////
//Enters strings, and returns size of the strings.
//Will not count Line breaks as a character.
//Going under or over a limit will trigger a reroute.
/////////////////////////////////////////////////
int Input_String(char str[])
{
printf("\nPlease input a string of numbers.\n");
printf("Tap enter again once finnished: \n\n");
int i=0;
while ((str[i] = getchar()) != '\n')
i++;
str[i+1]='\0';
return i;
if (i>MAX_SIZE-1 || i<MIN_SIZE)
{
printf("Your sumbition dosn't fit the size criteria.\n");
printf("Please reenter:\n\n");
Input_String(str);
}
}
/////////////////////////////////////////////////
//Tolkenizes string, Atoi each token into cute little ints.
//Each int will be sent to the Dynamic_Fitting to be assimilated into Main_Array
//Main_Size is passed into this function just to be used as parameters for the fitting.
/////////////////////////////////////////////////
int Token_Atoi(char str[], int numElements, int* Main_Array, int Main_Size)
{
char* temp = strtok(str, " -");
int i=0;
while (temp != NULL)
{
printf("String tokenize check: %s\n", temp);
Main_Size = Dynamic_Fitting(Main_Array, atoi(temp), Main_Size);
//Main size should be upgraded with each loop of the above line.
temp = strtok(NULL, " -");
i++;
}
return Main_Size;
}
/////////////////////////////////////////////////
//Will first increase the size of the dynamically allocated array of ints by 1 int
//Then, it will add the incomming int into the re-sized dynamic space.
//Main size serves as a bookmark to show where on the array the new realloc'd spot should be.
/////////////////////////////////////////////////
int Dynamic_Fitting(int* Main_Array , int Incomming_int , int Main_Size)
{
realloc(Main_Array, sizeof(int));
Main_Array[Main_Size]= Incomming_int;
printf("Dynamic fitting check: %i put into Main_Array[%i]\n\n", Incomming_int, Main_Size);
return Main_Size+1;
}
/////////////////////////////////////////////////
//Close shop
/////////////////////////////////////////////////
void Free_All(int* Main_Array)
{
free(Main_Array);
}
The line
realloc(Main_Array, sizeof(int));
is wrong. realloc returns a pointer that may point to new memory so when you dereference Main_Array on the next line you may be accessing freed memory. Also, you need to pass the full size of the updated memory buffer, not just the delta.
You could fix things by changing Dynamic_Fitting to something like
int Dynamic_Fitting(int** Main_Array , int Incomming_int , int Main_Size)
{
int* temp = realloc(Main_Array, (Main_Size +1) * sizeof(int));
if (temp == NULL) {
return -1; /* caller must handle oom error */
}
*Main_Array = temp;
(*Main_Array)[Main_Size] = Incomming_int;
printf("Dynamic fitting check: %i put into Main_Array[%i]\n\n", Incomming_int, Main_Size);
return Main_Size+1;
}
and calling it like
Main_Size = Dynamic_Fitting(&Main_Array, ....);
if (Main_Size == -1) {
/* out of memory. cleanup and exit program */
}
I guess this is one of the issue.
you have shared a very bog code and analysing everything is bit of a task... see if below issue solves your issu..
int Input_String(char str[])
{
printf("\nPlease input a string of numbers.\n");
printf("Tap enter again once finnished: \n\n");
int i=0;
while ((str[i] = getchar()) != '\n') // HERE if user enters more than array Size it will fail... with exception
i++;
str[i+1]='\0';
return i; /// THIS is wrong.. following if will never execute..
if (i>MAX_SIZE-1 || i<MIN_SIZE)
{
printf("Your sumbition dosn't fit the size criteria.\n");
printf("Please reenter:\n\n");
Input_String(str);
}
}
I will suggest below
int Input_String(char str[])
{
printf("\nPlease input a string of numbers.\n");
printf("Tap enter again once finnished: \n\n");
int i=0;
while ((str[i] = getchar()) != '\n') {
i++;
if (i>MAX_SIZE-1 || i<MIN_SIZE)
{
printf("Your sumbition dosn't fit the size criteria.\n");
printf("Please reenter:\n\n");
Input_String(str);
break;
}
}
str[i+1]='\0';
return i;
}