0

I am trying to read in a string from the user input and then print it on screen. However, when the string is printed on the console, it is kind of gibberish. The funny thing is that it works in Visual Studio and not in CodeBlocks.

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

int main() {
    int i, num_bytes;
    char sentence[] = "";
    std::cout << "Please enter your name: ";
    //fgets(sentence, 100, stdin);
    //scanf("%[^\n]%*c", sentence);
    //scanf("%[^\n]", sentence);
    std::cin >> sentence;
    num_bytes = strlen(sentence);

    LPVOID ptr = VirtualAlloc(NULL, num_bytes, MEM_RESERVE, PAGE_READWRITE);
    ptr = VirtualAlloc(ptr, num_bytes, MEM_COMMIT, PAGE_READWRITE);

    if (ptr) {
        char* char_ptr = static_cast<char*>(ptr);

        for (i = 0; i < num_bytes; i++) {
            char_ptr[i] = sentence[i];
        }

        std::cout << "Allocated Memory Address: " << (void *)ptr << std::endl;

        std::cout << "Press Enter to print out the characters.\n";
        getchar();

        for (i = 0; i < num_bytes; i++) {
            std::cout << char_ptr[i];
        }

        std::cout << "\nPress Enter to clear memory." << std::endl;
        getchar();

        VirtualFree(ptr, 0, MEM_RELEASE);
    } else {
        std::cout << "Could not allocate " << num_bytes << " of memory." << std::endl;
    }

    std::cout << "\nPress Enter to continue." << std::endl;
    getchar();
}
drescherjm
  • 10,365
  • 5
  • 44
  • 64
nab saw
  • 15
  • 3
  • 2
    Did you expect the compiler to provide an infinite amount of writable storage under `sentence`? Use `std::string` instead and forget about reserving storage up front. – Botje Dec 22 '21 at 14:06
  • `char sentence[] = "";` provides space for 0 characters + null terminator. This is a compile time sized array that will never expand from this size. – drescherjm Dec 22 '21 at 14:07
  • uses std::string instead of char[N]. But that's all that VirtualAlloc/VirtualFree. What are you doing? – Marius Bancila Dec 22 '21 at 14:13
  • After you enlarge the array to accept more than 0 characters are you sure that the person typing will not type a space character? Remember that `std::cin >> sentence;` will stop reading at the first white space character typed. – drescherjm Dec 22 '21 at 14:22
  • Yes, I am assuming the input will contain spaces. So, how do I resolve that issue? – nab saw Dec 22 '21 at 14:27

2 Answers2

2

You should explicitly specify memory size for string. That code:

char sentence[] = "";

declares sentence with max size is 0 (+1 zero symbol). Of course, you write more data into not-your memory. Try this:

char sentence[200] = "";
Evgeny
  • 1,072
  • 6
  • 6
  • What about spaces? Won't it null terminate at the first occurrence of a space character? – nab saw Dec 22 '21 at 14:28
  • Don't understand your question :(. You declare the 'sentence ' as "". It means character array with single symbol: \0 (zero symbol, it is not a space symbol). If you want to input string into that variable, you should allocate enough size: 200 - 1000 - 5000. But, anyway, code like that is way to crack your application. It is recommended to use std::string instead of raw char array. – Evgeny Dec 22 '21 at 14:34
  • @nabsaw "*Won't it null terminate at the first occurrence of a space character?*" - `operator>>` does, yes. Use `cin.getline()` instead (or switch to `std::string` and `std::getline()`) if you need to read strings with spaces. – Remy Lebeau Dec 22 '21 at 18:11
0

Instead of this:

    char sentence[] = "";
    std::cout << "Please enter your name: ";
    //fgets(sentence, 100, stdin);
    //scanf("%[^\n]%*c", sentence);
    //scanf("%[^\n]", sentence);
    std::cin >> sentence;
    num_bytes = strlen(sentence);

you better write this:

    constexpr std::streamsize BUFFER_SIZE { 100 };
    std::array<char, BUFFER_SIZE> sentence { }; // use the more modern std::array

    std::cout << "Please enter your name: ";
    std::cin.getline( sentence.data( ), BUFFER_SIZE ); // will only read 100 chars
                                                       // including spaces and tabs

    num_bytes = strlen(sentence.data( ));

and the rest is the same as your code. But now the user can enter space characters too and they can't cause a buffer overrun since std::cin.getline will only read a limited number of characters from standard input stream.

digito_evo
  • 3,216
  • 2
  • 14
  • 42
  • 1
    `cin.getline()` reports (via `cin.gcount()`) the number of characters written to `sentence`, so you don't need to use `strlen()` to determine `num_bytes`. – Remy Lebeau Dec 22 '21 at 18:10