troubleshooting Question

Segfault 11 on long string, PRIOR to accessing string, only when string > 14

Avatar of Mike R.
Mike R. asked on
C* Memory
13 Comments1 Solution209 ViewsLast Modified:
ANSI c on OSX 10.13.6 <br>
Apple LLVM version 9.1.0 (clang-902.0.39.2)
Target: x86_64-apple-darwin17.7.0
Thread model: posix

I'm learning `c`

This is a function that manually (character-by-character) adds two character strings representing large numbers (that exceed the unsigned long long or double size).

It functions fine with any two strings 14 or less characters long, but segmentation fault 11 with any strings greater than 14 chars.

Changing the string's memory allocation method seems to have no effect (I.e. from
char[15] addend1; // not a ptr
to
char *addend1 = (char *) malloc(sizeof(char) * (16) ); // pointer

One things that's curious, is that it seems to segfault on the ...
for (int j = maxlength - 1 ; j >= 0; j--)
... prior to accessing either of `addend1` or `addend2`, but I'm not able to find an error there or change it to prevent the segfault.  

Am I misreading where the error arises, or could it be related to the for loop?

MAIN.c

	#include <stdio.h>
	#include <stdlib.h>
	#include "../../c-library/include/addViaStrings.h"
	
	int main(void) {
		//	s[0] = 72; s[1] = 101; s[2] = 108; s[3] = 108; s[4] = 111; s[5] = 32; s[6] = 87; s[7] = 111; s[8] = 114; s[9] = 108; s[10] = 100; s[11] = 0;
	
		// WORKS
		// char s1[] = "14073748835532";
		// char s2[] = "14073748835532";
	
		// FAILS
		char s1[] = "140737488355328";
		char s2[] = "140737488355328";
	
		char *sum = addNumericStrings(&s1, &s2);
		printf("main.sum = %s\n", sum);
	}

addViaStrings.h

	char* addNumericStrings(char *s1, char *s2){
		// Find the length of the greater of the two
		int maxlength = findMaxLength(s1, s2);
		printf("maxlength = %d\n", maxlength); //333
	
		///////////////////////////////////////////////
		// Using malloc instead of char[maxlength] seems to have NO EFFECT on the issue
		// char addend1[maxlength]; // not a pointer
		char *addend1 = (char *) malloc(sizeof(char) * (maxlength + 1) );
		// char addend2[maxlength]; // not a pointer
		char *addend2 = (char *) malloc(sizeof(char) * (maxlength + 1) );
	
		// Allocate sum pointer
		printf("char *sum = (char *) malloc(sizeof(char) * (maxlength + 1) ) ... "); //333
		char *sum = (char *) malloc(sizeof(char) * (maxlength + 1) );
		printf("DONE\n"); //333
	
		// General use vars
		int a1, a2, total;
		int carry = 0;
	
		// Prepare the strings for manual addition. Pad the left with char 0s
		leftPad(addend1, s1, maxlength);
		leftPad(addend2, s2, maxlength);
	
		// Buffer sum with zeros
		sum[maxlength + 1] = 0; // end flag
		printf("for (int i = 0; i < (maxlength); i++) { sum[i] = '0'; } ... "); //333
		for (int i = 0; i < (maxlength); i++) { sum[i] = '0'; } // Fill w/ 0s
		printf("DONE\n"); //333
	
		// Run the manual addition
		// Start adding individual ints from end (right side)
		printf("Start adding individual ints from end (right side) ...\n"); //333
		for (int j = maxlength - 1 ; j >= 0; j--) {
			///////////////////////////////////////////
			// The segfault seems to happen BEFORE accessing addend1 or addend2
			printf("%d ..."); // 333 This DOES NOT print
			///////////////////////////////////////////
			a1 = addend1[j] - '0'; // Convert to int
			a2 = addend2[j] - '0'; // Convert to int
			total = (a1 + a2 + carry);
			carry = 0;
			if ( total >= 10){
				carry += 1;
				total -= 10;
			}
			sum[j + 1] = '0'+total; // convert to ascii value for numbers (adding 48)
		}
		sum[0] = '0' + carry; // add last carry to start of num always, even if 0
		// Before returning, truncate leading zeros
		char *returnsum = (char *) malloc(sizeof(char) * (strlen(sum) + 1) );
		int sum_i = 0;
		int returnsm_i = 0;
	//    bool truncate = true; // Find out why this wont compile
		int truncate = 1; // true
		while (1){
			// if order is important here
			if (sum[sum_i] == '\0') { break; } // we're done
			if (sum[sum_i] == '0' && truncate == 1) { sum_i += 1; continue; } // 1 is true
			// if a num, Stop truncating 0s but DO continue adding numbers
			if (sum[sum_i] != '0') { truncate = 0; } // 0 is false
			returnsum[returnsm_i] = sum[sum_i];
			returnsm_i += 1;
			sum_i += 1;
		}
		return returnsum;
	}
[\code]

[i][b]Successful run (less than 15 chars)[/b][/i]
[code]
    maxlength = 14
    char *sum = (char *) malloc(sizeof(char) * (maxlength + 1) ) ... DONE
    for (int i = 0; i < (maxlength); i++) { sum[i] = '0'; } ... DONE
    Start adding individual ints from end (right side) ...
    13 ...12 ...11 ...10 ...9 ...8 ...7 ...6 ...5 ...4 ...3 ...2 ...1 ...0 ...main.sum = 28147497671064

UNSuccessful run (15 chars)
    maxlength = 15
    char *sum = (char *) malloc(sizeof(char) * (maxlength + 1) ) ... DONE
    for (int i = 0; i < (maxlength); i++) { sum[i] = '0'; } ... DONE
    Start adding individual ints from end (right side) ...
Join the community to see this answer!
Join our exclusive community to see this answer & millions of others.
Unlock 1 Answer and 13 Comments.
Join the Community
Learn from the best

Network and collaborate with thousands of CTOs, CISOs, and IT Pros rooting for you and your success.

Andrew Hancock - VMware vExpert
See if this solution works for you by signing up for a 7 day free trial.
Unlock 1 Answer and 13 Comments.
Try for 7 days

”The time we save is the biggest benefit of E-E to our team. What could take multiple guys 2 hours or more each to find is accessed in around 15 minutes on Experts Exchange.

-Mike Kapnisakis, Warner Bros