0

I'm trying to implement a C function char* strShiftLeft(char* str, int n) that takes in a string (str) and an int n, which represents how many chars to shift str to the left. For example, if we call it as strShiftLeft("Thomas", 2), the function should return a char pointer pointing to a string "omasTh" as we append the first 2 (n) chars to the end of string and shift every char 2 slots to the left.

However, for some reason, when I compile my program, it compiles fine but when I run it on my mac, my terminal keeps showing me:

zsh: bus error  ./a.out

Here's my code:

#include <stdio.h>
#include <stdlib.h>

char* strShiftLeft(char* str, int n)
{

    // If the passed in string is NULL, return NULL 
    if (str == NULL)
    {
        printf("NULL!\n");
        return NULL;
    }

    // Get the length of the string
    int len = 0;
    char* counter_ptr = str;
    while (*counter_ptr != '\0')
    {
        len++;
        counter_ptr++;
    }

    printf("len: %d\n", len);

    // If the integer is longer than the string, return back NULL
    if (n > len)
    {
        printf("n too big!\n");
        return NULL;
    }

    // Create a temp char array to store 1st n chars to append to the end of string later
    char temp_arr[n];
    for (int i = 0; i < n; i++)
    {
        *(temp_arr + i) = *(str + i);
    }

    printf("temp_arr = %s\n", temp_arr);
    printf("str is still: %s\n", str);

    // So far so good

    char* temp = str + n;
    printf("len - n = %d\n", len - n);


    // Update first (len - n) characters of the string (e.g. n = 2, "Thomas" -> "omasas")
    for (int i = 0; i < (len - n); i++)
    {
        printf("*temp = %c\n", *temp);
        printf("*(temp - n) = %c\n", *(temp - n));

        
        *(temp - n) = *(temp); // THIS LINE SEEMS TO BE THE ONE CAUSING ERRORS
        temp++;
    }


    temp = str + (len - n);
    for (int i = 0; i < n; i++)
    {
        *(temp + i) = *(temp_arr+i); // THIS LINE ALSO SEEMS TO BE CAUSING ERRORS
    }


    return str;
}



int main()
{
    char* str = strShiftLeft("Thomas", 2);
    printf("%s\n", str); // Should print out "omasTh"

    return 0;
}

I used a lot of printf()s to try to find out what went wrong. I noticed two particular lines of code seem to be causing some errors, namely: 1)

*(temp - n) = *(temp); 
*(temp + i) = *(temp_arr+i);

What I'm trying to do with these 2 lines of code is that I want to update the values of certain elements in the string with values from other elements in the string.

Although my code compiles, when I run it, it shows "zsh: bus error ./a.out". I tried using some online compiler. When I ran my code, I got seg fault.

I don't know what mistakes I've made.

Would be much appreciated if someone can help me identify the mistakes I've made.

Note that, I'm not allowed to use dynamic memory allocation, bracket operator for dereferencing pointers, or any functions from the C library such as strlen(), strcpy() etc. Thanks!

I've used printf() to pinpoint which lines are causing errors, but I don't understand why they're causing errors.

  • Does this answer your question? [What is the difference between char s\[\] and char \*s?](https://stackoverflow.com/questions/1704407/what-is-the-difference-between-char-s-and-char-s) – Oka Dec 22 '22 at 08:05
  • You are attempting to modify read-only memory. For starters, try `char str[] = ""Thomas"; strShiftLeft(str, 2);`. – Oka Dec 22 '22 at 08:11
  • 1
    Also, if you are hoping to become a programmer, then stop using `printf()` for debugging and start using a debugger instead. – Mike Nakis Dec 22 '22 at 08:12
  • 2
    @MikeNakis Don't belittle the world's simplest debugger :-) – Support Ukraine Dec 22 '22 at 08:30
  • OT: I would rather call the function `strRotateLeft` – Support Ukraine Dec 22 '22 at 08:34
  • `temp_arr[]` is an array of characters in want of a terminating '\0' (because it is fed to `printf()` as if it were a string... Fix that for starters... – Fe2O3 Dec 22 '22 at 08:39
  • @SupportUkraine sure, but unfortunately, the world's simplest debugger may sometimes be responsible for causing your program to crash, and this question seems to be an example of precisely that. – Mike Nakis Dec 22 '22 at 10:54

1 Answers1

0

When you invoke strShiftLeft("Thomas", 2); you are passing strShiftLeft() the address of a string literal.

strShiftLeft() then proceeds to try and modify in-place the string that you passed to it, which means that it tries to modify a string literal.

Modifying a string literal in C is "undefined behavior", which means that anything may happen.

Anything includes:

  • Nothing. This will happen if you are running in some environment which happens to be storing C string literals in read-write memory. (And is treacherous, because it might give you the impression that your program works, while it doesn't.)
  • Bowls of petunias and sperm whales fall from the sky. (Mandatory HGGTG reference.)
  • More likely: Your program gets terminated due to a segmentation fault (segfault) because the string literal was stored in read-only memory and your program attempted to write to that memory.

However, this is not what is happening in your case, because you are not receiving a segfault, you are receiving a bus error. A bus error means that your program did not just attempt to write to read-only memory; it means that it attempted to address memory which cannot even be addressed.

What is causing your bus error is most probably the following:

printf("temp_arr = %s\n", temp_arr);

What happens is that you forgot to null-terminate your temp_arr, so the printf() function prints whatever temp_arr contains and then continues printing after the end of temp_arr. Since temp_arr is in the stack, printf() attempts to read from memory past the end of the stack, which is in all likelihood some invalid page.

This is one more reason to start using a debugger and stop using printf() statements.

Mike Nakis
  • 56,297
  • 11
  • 110
  • 142