I've written a program that will check if a given string has all characters unique or not. I usually write in Python, but I'm learning C and I wanted to write the program using it. I get an error when I translate Python into C : Thread 1: EXC_BAD_ACCESS (code=257, address=0x100000001)
I am using Xcode. When I run this program, I get the above error:
#include <iostream>
using namespace std;
int isUnique(string str) {
int arr[] = {};
for (int i = 0; i < str.length(); i) {
arr[i] = 0;
}
for (int j = 0; j < str.length(); j) {
arr[j] = 1;
}
for (int k = 0; k < sizeof(arr)/sizeof(arr[0]); k) {
if (arr[k] > 1) {
return false;
}
}
return true;
}
int main() {
string str;
cout << "Enter a string: ";
getline(cin, str);
cout << isUnique(str) << endl;
}
Here is the original code I wrote in Python:
def is_unique(string):
chars = []
for i in range(len(string)):
chars.append(0)
chars[string.find(string[i])] = 1 # I am using find and not just i because I want the first occurrence of the substring in the string to update it to 2 if it happens twice, 3 if it is thrice, etc.
for k in chars:
if k > 1: # Note that I'm checking for > 1
return False
return True
# Driver code
if __name__ == "__main__":
print(is_unique("abcd"))
When run, this outputs True
, which means that the string has unique characters only. Change print(is_unique("abcd")
to something else with a word without only unique characters, such as print(is_unique("hello")
to get False.
When I translated this into C , the Xcode terminal shows '(lldb)', and the Xcode editor opens up a file 0_mh_execute_header
and its contents are as follows:
dsa`_mh_execute_header:
0x100000000 < 0>: .long 0xfeedfacf ; unknown opcode
0x100000004 < 4>: .long 0x0100000c ; unknown opcode
0x100000008 < 8>: udf #0x0
0x10000000c < 12>: udf #0x2
0x100000010 < 16>: udf #0x12
0x100000014 < 20>: udf #0x638
0x100000018 < 24>: .long 0x00218085 ; unknown opcode
0x10000001c < 28>: udf #0x0
0x100000020 < 32>: udf #0x19
0x100000024 < 36>: udf #0x48
0x100000028 < 40>: .long 0x41505f5f ; unknown opcode
0x10000002c < 44>: saddwt z7.h, z10.h, z26.b
0x100000030 < 48>: udf #0x4f52
0x100000034 < 52>: udf #0x0
0x100000038 < 56>: udf #0x0
0x10000003c < 60>: udf #0x0
0x100000040 < 64>: udf #0x0
0x100000044 < 68>: udf #0x1
0x100000048 < 72>: udf #0x0
0x10000004c < 76>: udf #0x0
0x100000050 < 80>: udf #0x0
0x100000054 < 84>: udf #0x0
...
NOTE: ...
in the above means that it continues on. Stack Overflow allows only 30000 characters in the body, but this will exceed 950000
On line 1, Xcode shows an error: Thread 1: EXC_BAD_ACCESS (code=257, address=0x100000001)
on the right side of the file (like it usually does when there are compiler issues).
Do you know how to solve this?
CodePudding user response:
The problem lies here:
int arr[] = {};
Arrays in C and C are not dynamic. What you have created there is an array with 0 elements, and that's what it forevermore will be. So, when you do:
arr[i] = 0;
you are writing off the end of the array into random memory. If you want the array to be the same length as the string, you would need:
int arr[str.size()];
Or, use a vector:
std::vector arr(str.size());
CodePudding user response:
The problem is here:
int arr[] = {};
The array you're creating has length 0
which you can verify using
cout << "sizeof(arr): " << sizeof(arr) << endl;
The error occurs when you try to access values beyond the size of the array here:
arr[i] = 0;
What you need to do is specify a size of the array, for example int arr[128];
which creates an array that can hold 128 int
s, which covers the range of 7-bit-ASCII. Or use a vector, which you can change the size of.
I will also point out that the logic as it is doesn't work, what you might want to do is
int isUnique(string str) {
// Create an array that holds 128 ints and initialize it to 0
int arr[128] = {0};
// First loop no longer needed
for (int i = 0; i < str.length(); i) {
// Increment count for cell that corresponds to the character
char c = str[i];
arr[c] = 1;
}
// Note that you can reuse variable name when previous one
// has fallen out of scope
for (int i = 0; i < sizeof(arr)/sizeof(arr[0]); i) {
if (arr[i] > 1) {
return false;
}
}
return true;
}
I suggest you read more on the C memory model.