Study Guide 2
Code Jams are open book. 40 minutes in lab.
Topics:
Everything from Study Guide 1, plus
-
valgrind/gdb
-
Common memory errors
-
malloc/free
-
2D arrays
-
Reading and writing text files
Write C programs to check your answers. Or you can ask a TA or instructor to give feedback on your responses.
Practice questions
1) When Bella runs valgrind on her program, she receives the following error
==2017== Conditional jump or move depends on uninitialised value(s)
==2017== at 0x483EF49: strlen (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==2017== by 0x1091D4: main (memerr.c:6)
Here is her code
#include <stdio.h>
#include <string.h>
int main() {
char name[16];
for (int i = 0; i < strlen(name)-1; i++) {
name[i] = i+'a';
}
name[15] = '\0';
printf("Name is %s\n", name);
return 0;
}
What does the valgrind error mean and how can Bella fix her program?
2) When Garfield runs valgrind on his program, he received the following error
free(): double free detected in tcache 2
Aborted
Here is his code.
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE* fp = fopen("test.txt", "r");
if (!fp) {
printf("Cannot open file\n");
exit(1);
}
int ch = 0;
while (ch != EOF) {
ch = fgetc(fp);
}
fclose(fp);
free(fp);
fp = NULL;
}
What does the valgrind error mean and how can Garfield fix his program?
3) When Billie runs their program it crashes with the following error.
segmentation fault
Here is their program
/*
* Copyright (c) 2020, Dive into Systems, LLC (https://diveintosystems.org/)
* Program with a segfault
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int initfunc(int *array, int len) {
int i;
for (i=1; i <= len; i++) {
array[i] = i;
}
return 0;
}
int func(int *array1, int len, int max) {
int i;
max = array1[0];
for (i=1; i <= len; i++) {
if (max < array1[i]) {
max = array1[i];
}
}
return 0;
}
int main(int argc, char *argv[]) {
int *arr = NULL;
int max = 6;
if (initfunc(arr, 100) != 0 ) {
printf("init error\n");
exit(1);
}
if ( func(arr, 100, max) != 0 ) {
printf("func error\n");
exit(1);
}
printf("max value in the array is %d\n", max);
exit(0);
}
Let’s help Billie use GDB to find and fix their crash.
-
What is a segmentation fault?
-
What GDB command can we use to place a breakpoint at the start of the functions
main
andinitfunc
? -
What GDB command can we use to execute the next line?
-
How do you print the parameters of
initfunc
? -
What line of the program contains the error? Is it the same line as the crash? What is happening and how can Billie fix their program?
4) Draw the function stack and heap for the following program.
-
Draw the stack and heap the first time the line labeled A is reached
-
Draw the stack and heap the first time the line labeled B is reached
-
Draw the stack and heap the first time the line labeled C is reached
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct link {
char name[16];
struct link* children[4];
};
struct link* create(const char* name, struct link* parent) {
struct link* limb = malloc(sizeof(struct link));
strncpy(limb->name, name, 15);
// A) Draw function stack here
return limb;
}
void clear(struct link* body[], int n) {
for (int i = 0; i < n; i++) {
free(body[i]);
body[i] = NULL;
}
// C) Draw function stack here
}
int main() {
struct link* body[4];
body[0] = create("root", NULL);
body[1] = create("head", body[0]);
body[2] = create("left arm", body[0]);
body[3] = create("right arm", body[0]);
// B) Draw function stack here
clear(body, 4);
return 0;
}
6) Draw the stack diagram for the following program. Does the list get created correctly? Why or why not?
#include <stdio.h>
#include <stdlib.h>
struct node {
int val;
struct node* next;
};
struct node* insert_front(int val, struct node* head) {
struct node* n = malloc(sizeof(struct node));
if (n == NULL) {
printf("ERROR: Out of space!\n");
exit(1);
}
n->val = val;
n->next = head;
return n;
}
void print(struct node* list) {
for (struct node* n = list; n != NULL; n = n->next) {
printf("Val: %d\n", n->val);
}
}
int main() {
struct node* n3 = insert_front(2, NULL);
// draw stack here
struct node* n2 = insert_front(1, n3);
struct node* n1 = insert_front(0, n2);
free(n1);
free(n2);
free(n3);
}
7) Draw the stack diagram for the following program. Does the list get created correctly? Why or why not?
struct node {
int val;
struct node* next;
};
void insert_front(int val, struct node** head) {
struct node* n = malloc(sizeof(struct node));
if (n == NULL) {
printf("ERROR: Out of space!\n");
exit(1);
}
n->val = val;
n->next = *head;
*head = n;
}
int main() {
struct node *head = NULL;
insert_front(0, &head);
// draw stack here
insert_front(1, &head);
insert_front(2, &head);
}
8) Write a program that reads in a text file and writes it to a new file with each word reversed.
9) Write a program that swaps the first and last element of a linked list.