C: clang gives segfaults on Mac - gcc

Below is the program which converts a sorted Array to BST. I am able to compile and execute the program using an online C compiler. When I tried the compile on my local system, it is throwing a segmentation fault.
SortedArraytoBST.c
#include <stdio.h>
#include <stdlib.h>
// Structure of the node
struct TNode
{
int data;
struct TNode* left;
struct TNode* right;
};
struct TNode* newNode(int data);
// Function that converts array to BST
struct TNode* SortedArrayToBST(int arr[], int start, int end)
{
if(start > end)
{
return NULL;
}
if(start == end)
{
struct TNode* newnode2 = newNode(arr[start]);
return newnode2;
}
int mid = (start+end)/2;
struct TNode* newnode = newNode(arr[mid]);
newnode->left = SortedArrayToBST(arr, start, mid-1);
newnode->right = SortedArrayToBST(arr, mid+1, end);
return newnode;
}
//NewNode Creation
struct TNode* newNode(int data)
{
struct TNode* node = (struct TNode*)malloc(sizeof(struct TNode*));
node->data = data;
node->left = NULL;
node->right = NULL;
return node;
}
// Print the tree in preorder
void preorder(struct TNode* node)
{
if( node == NULL) return;
printf("%d\n", node->data);
preorder(node->left);
preorder(node->right);
}
// Array to BST
int main()
{
int arr[]={1,2,3};
int size = sizeof(arr)/sizeof(arr[0]);
struct TNode* root = SortedArrayToBST(arr, 0, size-1);
preorder(root);
return 0;
}
Command used to compile the program
$ gcc -o SortedArraytoBST SortedArraytoBST.c
$ gcc --version
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.2.0
Thread model: posix
$
Output of the program on my local Mac
2
-398445936
Segmentation fault: 11
Output of the program on http://code.geeksforgeeks.org/
2
1
3

Line 36, you have a wrong allocation causing a heap-buffer-overflow.
You should write:
struct TNode* node = (struct TNode*)malloc(sizeof(struct TNode));
instead of:
struct TNode* node = (struct TNode*)malloc(sizeof(struct TNode*));
HOW TO DEBUG IT
If you get gcc 4.8 or above, you can run address sanitizer:
gcc -fsanitize=address -fno-omit-frame-pointer -g myprogram.c -o myprogram
What I got:
=================================================================
==22711==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000eff8 at pc 0x000000400bbb bp 0x7ffea7e3c630 sp 0x7ffea7e3c628
WRITE of size 8 at 0x60200000eff8 thread T0
#0 0x400bba in newNode /home/jyvet/TMP/myprogram.c:38
#1 0x400aac in SortedArrayToBST /home/jyvet/TMP/myprogram.c:27
#2 0x400d75 in main /home/jyvet/TMP/myprogram.c:57
#3 0x7f68db2c7b44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b44)
#4 0x4008e8 (/home/jyvet/TMP/myprogram+0x4008e8)
0x60200000eff8 is located 0 bytes to the right of 8-byte region [0x60200000eff0,0x60200000eff8)
allocated by thread T0 here:
#0 0x7f68db6e337a in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x9437a)
#1 0x400b59 in newNode /home/jyvet/TMP/myprogram.c:36
#2 0x400aac in SortedArrayToBST /home/jyvet/TMP/myprogram.c:27
#3 0x400d75 in main /home/jyvet/TMP/myprogram.c:57
#4 0x7f68db2c7b44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b44)
SUMMARY: AddressSanitizer: heap-buffer-overflow /home/jyvet/TMP/myprogram.c:38 newNode

Related

C++ binary search tree template class memory leak

Newbie question. I am trying to program a binary search tree, but even
a simple insert has a memory leak.
File Node.h
template<typename X> struct Node {
X value;
Node* left;
Node* right;
Node(X x) {
this->value = x;
this->left = nullptr;
this->right = nullptr;
}
};
File BST.h
template <typename X> class BST {
public:
BST() { root = nullptr; }
bool Insert(const X& x) { return InsertAt(root, x); }
private:
bool InsertAt(Node<X>*& node, const X& x)
{
if (node == nullptr) {
node = new Node<X>(x);
return true;
}
if (node->value == x)
return false;
if (*(node->value) > *x)
return InsertAt(node->left, x);
return InsertAt(node->right, x);
}
//----
Node<X>* root;
};
The main program
#include "Node.h"
#include "BST.h"
int main(int argc, char **argv)
{
BST<int*> bst;
bst.Insert(new int(8));
}
The output of g++ -g -fsanitize=address -fno-omit-frame-pointer -std=c++11 B.cpp
==10646==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 24 byte(s) in 1 object(s) allocated from:
#0 0x7fb5e7f45532 in operator new(unsigned long) (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x99532)
#1 0x400eb7 in BST<int*>::InsertAt(Node<int*>*&, int* const&) /home/gc/BST.h:12
#2 0x400e68 in BST<int*>::Insert(int* const&) /home/gc/BST.h:5
#3 0x400d09 in main /home/gc/B.cpp:22
#4 0x7fb5e778082f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
Indirect leak of 4 byte(s) in 1 object(s) allocated from:
#0 0x7fb5e7f45532 in operator new(unsigned long) (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x99532)
#1 0x400caf in main /home/gc/B.cpp:22
#2 0x7fb5e778082f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
SUMMARY: AddressSanitizer: 28 byte(s) leaked in 2 allocation(s).
First, why am I getting a memory leak? Second, why am I getting a message
about new(unsigned long) when there is nothing unsigned long about my program?
Thanks.
You may tell me to use smart pointers, but for right now I'm just trying to
educate myself about pointers and trying to figure out why this doesn't work.
If you're not going to use smart pointers, then you have to pair every new with a delete. Since your calls to new happen in each class's constructor, you can delete in the destructor.
Anyways, in BST the destructor should be
~BST() { delete root; }
And in Node, it's
~Node() { delete left; delete right; }
This will recursively work it's way down the tree. Your recursive case is when a pointer to a node is not null. Unlike with free which crashes on a null, delete simply does nothing, making nullptr your base case.
Check out http://en.cppreference.com/w/cpp/language/destructor

Initializing a doubly linked list from array parameters

C++ noob reporting in. I'm trying to write a function that will create and initialize a doubly linked list using values that are stored in two different arrays. Here's how my linked list class is set up:
class node {
public:
node *prev;
node *next;
int key;
char type;
};
and here's how my dList class (containing various functions to alter my linked list) is set up:
class dList {
private:
node *head; // dummy head
node *tail; // dummy tail
public:
dList() { // default constructor, creates empty list
head = tail = NULL;
}
~dList() { // deconstructor
node *ptr = head;
while (head != NULL) {
head = head->next;
delete ptr;
}
tail = NULL;
}
dList(int arrayNums[], char arrayChars[], int size); // parametrized constructor, initialize list w/ contents of arrays
void addFront(int k, char t); // creates new node at front of list
void addBack(int k, char t); // creates new node at back of list
node *search(int k); // searches list for occurence of int parameter and returns pointer to node containing key
void find(char t); // outputs all keys that have type equal to character parameter, front to back
void moveFront(node* ptr); // moves node pointed to by parameter to front of list
void moveBack(node* ptr); // moves node pointed to by parameter to back of list
void out(int num, char = 'f'); // outputs first int elements of list, starting at front or back depending on char parameter
void sort(); // peforms a quick or mergesort on items; list should be in increasing order based on integer key
};
I need help implementing my parametrized constructor. Could someone tell me if the function I have now is written correctly? I think it is, but when I run my program, it runs forever--a clear problem. Here's my function as-is:
dList::dList(int arrayNums[], char arrayChars[], int size) {
node *newNode = NULL;
for (int i = 0; i < size; i++) {
if (head == NULL) {
newNode = new node;
newNode->key = arrayNums[i];
newNode->type = arrayChars[i];
newNode->prev = NULL;
newNode->next = NULL;
head = newNode;
tail = newNode;
}
else { // needs work!
newNode = new node;
newNode->key = arrayNums[i];
newNode->type = arrayChars[i];
newNode->prev = tail;
tail->next = newNode;
tail = newNode;
}
if (i == (size - 1)) {
tail->next = NULL;
}
}
}
Thank you very much!
EDIT: here is my main.cpp (code I'm using to test my dList.cpp file)
#include <iostream>
using namespace std;
#include "dList.cpp"
#define SMALL 200
#define MAX 100000
#define ROUNDS 100
int main(){
int i, x[MAX];
char ch[MAX];
for(i=0;i<SMALL;i++) {
x[i] = 2 * (SMALL - i);
ch[i] = 'a' + (i % 26);
}
dList A(x,ch,SMALL), B;
A.out(10);
node *tmp = A.search(2*SMALL-8);
A.moveFront(tmp);
A.out(10);
A.moveBack(tmp);
A.out(10);
A.find('b');
A.sort();
A.out(10);
A.out(10,'b');
A.addBack(500,'d');
A.addFront(501,'z');
A.out(10);
A.out(10,'b');
B.addFront(1,'a');
B.addBack(2,'b');
B.out(2);
for(int j=0; j<ROUNDS; j++){
cout << endl << "round " << j << endl;
for(i=0;i<MAX;i++) {x[i] = 2*MAX-i; ch[i] = 'a'+ (i%26);}
dList A(x,ch,MAX);
node *tmp = A.search(2*MAX-8);
A.moveFront(tmp);
A.moveBack(tmp);
A.sort();
A.out(10);
A.out(10,'b');
}
}

Storing words into a hashtable

I have a file that contains English words in a txt file, each word in a new line.
I'm a beginner in C. I'm using a load and unload functions to store all the words into a hashtable (separate chaining) and unload them from memory, but has ran into some problems.
The functions (the code in main.c is correct):
load:
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
#include "dictionary.h"
#define SIZE 26
typedef struct node
{
char word[LENGTH+1];
struct node *next;
}node;
unsigned int hash_num = 0;
node *hashtable[SIZE]; //26 letters in alphabet
node *head = NULL;
// hashfunction
unsigned int hash(char const *key)
{
unsigned int hash= tolower(key[0]) - 'a';
return hash % SIZE;
}
/**
* Loads dictionary into memory. Returns true if successful else false.
*/
bool load(const char* dictionary)
{
unsigned int hash_index=0;
FILE *fp = fopen(dictionary, "r");
if(fp == NULL)
{
fprintf(stderr, "Couldn't open %s",dictionary);
return false;
}
//dictionary
while(!feof(fp))
{
node *temp = malloc(sizeof(node));
if (temp == NULL)
{
unload();
fclose(fp);
return false;
}
if(fscanf(fp , "%s", temp->word) == 1) //storing word of dictionary in my new_node -> word
{
hash_index = hash(temp->word);
head= hashtable[hash_index]; //head always points to first element of linked list (containting word of dictionary)
temp->next = head;
head = temp;
hash_num++;
}
else //if fscanf couldn't store the word (return 0)
{
free(temp); //free last temp
break;
}
}
fclose(fp);
return true;
}
unload:
bool unload(void)
{
for(int i=0; i<SIZE; i++)
{
if(hashtable[i] != NULL) //if hashtable isn't NULL (has nodes)
{
node *cursor = hashtable[i]; //cursor points at head of individual linked list
while(cursor != NULL) //free them
{
node *temp = cursor;
cursor = cursor->next;
free(temp);
}
}
}
return true;
}
Can anyone tell me if the logic is correct? Whenever I run valgrind it tells me that all my nodes were allocated but just 3 free'd.
total heap usage: 143,094 allocs, 3 frees, 8,014,288 bytes allocated
LEAK SUMMARY:
==15903== definitely lost: 8,013,040 bytes in 143,090 blocks
==15903== indirectly lost: 0 bytes in 0 blocks
==15903== possibly lost: 0 bytes in 0 blocks
When checking the provided source code (missing "dictionary.h"), the main problem is locating in the load() function.
Problem 1 (Main) - the hashtable[] is never updated when adding a new word/node (after computing hash_index = hash(temp->word);).
To store the updated linked-list (managed as reversed), it is
necessary to update the hashtable[hash_index] with the new node
pointer (the allocated temp node).
temp->next = head;
head = temp;
hashtable[hash_index] = head; // update the hashtable[] pointer
hash_num++;
Alternate solution without global variable head.
temp->next = hashtable[hash_index]; //head always points to first element...
hashtable[hash_index] = temp; // update the hashtable[] pointer
hash_num++;
Instead of
temp->next = head;
head = temp;
hash_num++;
Problem 2 (Small) - the hashtable[SIZE] is never initialized.
In the unload() function, in the for-loop, the if-condition
if(hashtable[i] != NULL) assumes that each item of the array is
initialized to NULL.
Add at the beginning the load() function or before calling it, a for-loop to initialize each pointer.
for(int i=0; i<SIZE; i++)
{
hashtable[i] = NULL;
}
Problem 3 (Potential Bug Source) - as suggest by reviewer, the use of head, declared as a global variable node *head = NULL; could be a potential source of bug.
In the load() function, the variable head is used as a temporary
storage but could store value during software run. If a read operation
is performed without a well-known write operation before, the result
could be an unexpected error even if the compilation doesn't detect
error or warning.
The best way is to reduce the number of global variable as much as
possible.
Enhancement (Reverse the linked-list) - because the managed linked-list is adding new items in the front, here is a solution to add new items in the end.
node *first = hashtable[hash_index];
if (first == NULL) {
hashtable[hash_index] = temp;
}
else {
temp->next = NULL; // ending the list
while (first->next!=NULL) {
first = first->next; // loop until last node
}
first->next = temp; // linking to the last node
}
hash_num++;
Instead of
head= hashtable[hash_index]; //head always points to first element ...
temp->next = head;
head = temp;
hash_num++;

linked list errors

I just test the function on one of the struct which is name but it won't reach them.
This is the full code so far:
update:
#include <iostream>
#include <string>
#include <cstdlib>
#include <cstddef>
using namespace std;
struct Node{
string name;
string address;
int phoneNum;
struct Node* next;
};
Node insertInOrder(Node p, string theName);
void push(struct Node*& head, string theName);
int main(){
cout<<"\tEnter S or s to show the list contents \n"
<<"\tEnter A or a to add a node to the list \n"
<<"\tEnter D or d to delete a node from the list \n"
<<"\tEnter Q or q to quiet the program \n"
<<"Make your selection: "<<endl;
struct Node* newNode = new Node;
push(newNode, "yeah");
cout<<newNode;
return 0;
}
void push(struct Node*& head, string theName){
struct Node* newNode = new Node;
newNode->name = theName;
newNode->next = head;
head = newNode;
}
Node insertInOrder(Node p, string theName){
if(p == NULL || p.name >= theName){
return new Node(p, theName);
}
else{
p.next = insertInOrder(p.next, theName);
return p;
}
}
I get an error that says: invalid application of ‘sizeof’ to incomplete type ‘Node’ for this code:
void push(struct Node*& head, string theName){
struct Node* newNode = malloc(sizeof(struct Node));
newNode->name = theName;
newNode->next = head;
head = newNode;
}
I'm trying to translate this code into my code but I got an error:
Node insertInOrder( int k, Node p ) {
if( p == " " || p.item >= k )
return new Node( k, p );
else {
p.next = insertInOrder( k, p.next );
return p;
}
}
This is how I translated it:
Node insertInOrder(Node p, string theName){
if(p == " " || p.name >= theName){
return new Node(p, theName);
}
else{
p.next = insertInOrder(p.next, theName);
return p;
}
}
here is the error for this code:
if(p == " " || p.name >= theName){
return new Node(p, theName);
Errors:
- comparison with string literal results in unspecified behaviour [-Waddress]
- request for member ‘name’ in ‘p’, which is of pointer type ‘Node*’ (maybe you meant to use ‘-
>’ ?)
- comparison between distinct pointer types ‘Node*’ and ‘const char*’ lacks a cast [-
fpermissive]
p.next = insertInOrder(p.next, theName);
return p;
errors:
Invalid arguments ' Candidates are: Node insertInOrder(Node, std::basic_string<char,std::char_traits<char>,std::allocator<char>>) '
- could not convert ‘p.Node::next’ from ‘Node*’ to ‘Node’
Some points:
forget malloc since you are working with C++ and use new and delete
you don't need to specify that node is a struct again whenever you use it so sizeof(Node) is enough, but you won't directly use malloc
your function Node insertInOrder(Node p, string theName) accepts a concrete Node and return a concrete Node but the field next inside your struct is a pointer to a Node, I guess you shoul be consistent in what you are using and since you are working with a linked list using pointers is more suitable
you can't use a comparison operator directly between a value and a string literal (p == " "), you should check name field only

Find and concatenate lines using sed

I have a struct blocks within a long c file
struct node {
int val;
struct node *next;
};
How do I use the sed function to find this struct block and convert it into one line. So it looks like this:
struct node { int val; struct node *next;};
Thanks in advance
My input is this:
struct node {
int val;
struct node *next;
};
typedef struct {
int numer;
int denom;
} Rational;
int main()
{
struct node head;
Rational half, *newf = malloc(sizeof(Rational));
head = (struct node){ 5, NULL };
half = (Rational){ 1, 2 };
*newf = (Rational){ 2, 3 };
}
My output is :
struct node { int val; struct node *next;};
typedef struct { int numer; int denom;} Rational;int main(){struct node head;Rational half, *newf = malloc(sizeof(Rational));head = (struct node){ 5, NULL };
half = (Rational){ 1, 2 };
*newf = (Rational){ 2, 3 };
}
I only want the struct node: struct node { int val; struct node *next;};
and the typedef struct: typedef struct { int numer; int denom;} Rational;
to be in one line. However int main() is being appended to the end of Rational;
I want the stuff in the main function to remain as it is.
With sed:
sed '/struct[^(){]*{/{:l N;s/\n//;/}[^}]*;/!t l;s/ */ /g}' input.c
When sed sees a struct definition (/struct[^{]*{/), it will read lines until a }; is seen on a line (:l N;s/\n//;/[}];/!t l;) while also removing newlines. When it matches }; it removes extra spaces (;s/ */ /g).

Resources