-1

I have a C++ function that is supposed to repeat a string a certain amount of times. What I've seen is that when the resulting string is more than 15 characters long, the function does not return anything, but it works as expected when the string is less than 16 characters long.
Here is the function:

const char* repeat(const char* str, int n) {
    std::string repeat;
    std::string s=std::string(str);

    for (int i = 0; i < n; i++) {
        repeat += s;
    }
    printf(repeat.c_str()); // this is for testing
    printf("\n");

    return repeat.c_str(); // It returns the same thing it prints
}

When using gdb, the output of the function is like this: (I added comments)

(gdb) print repeat("-",10)
---------- // prints 10 dashes
$1 = 0x7fffffffd9e0 "----------" // returns 10 dashes
(gdb) print repeat("-",15)
--------------- // prints 15 dashes
$2 = 0x7fffffffd9e0 '-' <repeats 15 times> // returns 15 dashes
(gdb) print repeat("-",16)
---------------- // prints 16 dashes
$3 = 0x5555555712c0 "" // returns nothing
(gdb) print repeat("-=",8)
-=-=-=-=-=-=-=-= // prints 8 "-="s
$4 = 0x5555555712c0 "" // returns nothing
(gdb) 

I have no idea what this is about.
PS: this is my first SO post so I'm not used to doing this.


Update

My understanding of C strings was wrong, I still don't fully understand them so I will stick to std::string. Returning const char* was the wrong thing because it returns a pointer to something only to be used once. This is my new code:

std::string repeat(std::string str, int n) {
    std::string repeat;

    for (int i = 0; i < n; i++) {
        repeat += str;
    }

    return repeat;
}

Thanks for the help!

CalSch
  • 3
  • 5
  • 1
    `c_str` returns a pointer to the `std::string`s internal buffer. The function returns a dangling pointer – 463035818_is_not_an_ai Aug 29 '22 at 18:13
  • 1
    What you observe is undefined behavior plus short string optimization – 463035818_is_not_an_ai Aug 29 '22 at 18:13
  • related https://stackoverflow.com/questions/10006891/stdstringc-str-and-temporaries – 463035818_is_not_an_ai Aug 29 '22 at 18:14
  • 1
    why do you not return a `std::string` ? Your function only returns a pointer. Pointers point somewhere. To store a string you need a string, not just a pointer – 463035818_is_not_an_ai Aug 29 '22 at 18:16
  • 1
    Before you start writing your function, look at the prototype. `const char* repeat(const char* str, int n)`. It returns a pointer. The pointer should be pointing to some memory. Where does this memory come from? When is it created? When is it destroyed? Who is responsible for destroying it? If you cannot answer these questions, don't start writing the function. Crack open a textbook instead. – n. m. could be an AI Aug 29 '22 at 18:17
  • I did not know that c_str did that, I thought it returned just a `const char*`, thanks for telling me! Also I want to return a `const char*` because of convenience for printing, and all the other string-related functions take it, so I will change them to a string instead of a `const char*` – CalSch Aug 29 '22 at 18:19
  • Also I'm pretty new to C++, so thanks for all the help! – CalSch Aug 29 '22 at 18:20
  • " I thought it returned just a const char*" yes, thats what it does return, and thats the issue – 463035818_is_not_an_ai Aug 29 '22 at 18:22

2 Answers2

0

The std::string variable repeat is local to your function. repeat.c_str() does not allocate a new char array and store the string in it. It simply returns a pointer to the internal storage for the std::string. In this case, that variable is no longer valid, so you've entered into the world of undefined behavior.

It is unclear why in C++ you are working with char arrays and printf at all, rather than using <iostream> and std::string.

Chris
  • 26,361
  • 5
  • 21
  • 42
0

You are invoking UB (Undefined Behavior) by returning a pointer into a string (repeat) that is locally declared and therefore de-allocated when your function returns. I'd suggest that you have your function actually return the string object itself instead of const char*.

Logicrat
  • 4,438
  • 16
  • 22