Проблемы с аргументами командной строки C++ в Windows

У меня почему-то возникают проблемы с разбором аргументов командной строки в Windows на С++. Я пытался использовать это

int main(int argc, char **argv)
{
    std::cout << "Command-line argument count: " << argc << " \n";
    std::cout << "Arguments:\n";
    for (int i = 0; i < argc; i++)
        std::cout << "  argv[" << i << "]   "
        << argv[i] << "\n";

    return 0;
}

а также это

int main(int argc, char *argv[])
{
    std::cout << "Command-line argument count: " << argc << " \n";
    std::cout << "Arguments:\n";
    for (int i = 0; i < argc; i++)
        std::cout << "  argv[" << i << "]   "
        << argv[i] << "\n";

    return 0;
}

Переменные argc и argv как-то не инициализированы. Вот что мне возвращает запуск программы:

Z:\Dev\ProcessSuspender\Debug>ProcessSuspender a
Command-line argument count: 2130558976
Arguments:
  argv[0]
  argv[1]   ╠ÉÉÉÉÉj↑h╚♂YwÞØ÷■ âe³
  argv[2]

(следующий сбой)

Я скомпилировал его с помощью MSVC12, используя параметр компоновщика /SUBSYSTEM:CONSOLE. Что может быть причиной этой проблемы?


person codefox    schedule 26.12.2014    source источник
comment
Вы всегда получаете одни и те же мусорные данные? Можете ли вы проверить, установлен ли _mainCRTStartup в качестве точки входа? Какую версию CRT вы используете?   -  person Rufflewind    schedule 26.12.2014
comment
В коде нет ничего плохого. Проверьте настройки вашего проекта.   -  person CroCo    schedule 26.12.2014
comment
@Rufflewind Я вручную установил точку входа на main. Независимо от того, использую ли я настройку проекта по умолчанию (_tmain) или нет, проблема сохраняется. Проект использует флаг /MDd. После установки значения /MTd приложение мгновенно вылетает при запуске. Я переустановлю VS и все остальное, что с ним связано, возможно, есть какие-то конфликты версий.   -  person codefox    schedule 26.12.2014
comment
@codefox Подождите секунду, вы сказали, что вручную установили точку входа на main? Это не сработает, точка входа должна быть точкой входа CRT, mainCRTStartup, как упоминалось выше Rufflewind (ну, за исключением того, что это указано в параметрах компоновщика без начального подчеркивания, насколько мне известно). Подробности смотрите в этом вопросе.   -  person bogdan    schedule 26.12.2014
comment
@bogdan Это также относится к приложениям командной строки? Насколько я знаю, это относится только к приложениям WinAPI. Кроме того, я изменил точку входа только после того, как заметил эту проблему.   -  person codefox    schedule 26.12.2014
comment
@codefox Это относится ко всем приложениям. Должен быть некоторый код, который анализирует командную строку, заданную ОС, и создает аргументы, необходимые для стандартного объявления main. Не говоря уже обо всех других вещах, которые должны произойти до вызова main.   -  person bogdan    schedule 26.12.2014
comment
@bogdan Спасибо, что указали на это. Сейчас работает без нареканий. Думаю, вот что происходит, когда вы переключаетесь с разработки *nix на Windows...   -  person codefox    schedule 26.12.2014
comment
@codefox Одно различие между /SUBSYSTEM:CONSOLE и /SUBSYSTEM:WINDOWS заключается в том, что, когда указан первый, точкой входа по умолчанию является mainCRTStartup, поэтому вам не нужно явно указывать его компоновщику.   -  person bogdan    schedule 26.12.2014


Ответы (4)


Я вручную установил точку входа на main. Независимо от того, использую ли я настройку проекта по умолчанию (_tmain) или нет, проблема сохраняется.

В общем, вы не должны этого делать, если не знаете последствий. Типичные значения точки входа (/ENTRY) должны быть следующими:

  • [w]mainCRTStartup, который вызывает [w]main, или
  • [w]WinMainCRTStartup, который вызывает [w]WinMain, или
  • _DllMainCRTStartup, который вызывает DllMain.

Зачем это нужно? Что ж, …CRTStartup-семейство функций делает пару важных вещей, включая инициализацию:

  • среда выполнения C (CRT),
  • любые глобальные переменные и
  • аргументы argc и argv, как вы случайно узнали.

Таким образом, для типичной программы вы, вероятно, захотите, чтобы она выполняла свою работу. В мире Linux существует эквивалентная функция с именем _start, которая необходима для выполнения тех же задач инициализации, которую можно переопределить с помощью -e при компоновке.

Путаница здесь, вероятно, связана с разницей в неоднозначном значении слова «точка входа»: есть значение «кажущаяся точка входа» с точки зрения языка (то есть main и ему подобные) и значение «истинной точки входа». точка входа" с точки зрения реализации языка (это …CRTStartup или _start).

Обратите внимание, что использование функций …CRTStartup не является абсолютно необходимым, поскольку вы, безусловно, можете написать программу, которая их не использует. Однако это имеет свою цену:

  • вы не можете использовать среду выполнения C, поэтому вы не можете использовать большую часть стандартной библиотеки,
  • вам нужно вручную инициализировать любые глобальные переменные, и
  • вам необходимо вручную получить argc и argv с помощью Windows API (GetCommandLineW и CommandLineToArgvW).

Некоторые делают это, чтобы избежать зависимости от CRT или минимизировать размер исполняемого файла.

person Rufflewind    schedule 26.12.2014
comment
Спасибо за подробное объяснение! В будущем я обязательно буду иметь это в виду. Эта проблема действительно сводила меня с ума, но теперь все работает просто отлично. - person codefox; 26.12.2014
comment
Не чините, если не сломано! - person Ajay; 27.12.2014

Я попробовал ваш проект на VS 2012, и он работает без сбоев. Я добавил getchar(); команда, как показано ниже:

#include <iostream>

int main(int argc, char *argv[])
{
    std::cout << "Command-line argument count: " << argc << " \n";
    std::cout << "Arguments:\n";
    for (int i = 0; i < argc; i++)
        std::cout << "  argv[" << i << "]   "
        << argv[i] << "\n";
    getchar();
    return 0;
}

чтобы я мог видеть результат.

Щелкните правой кнопкой мыши Проект -> Свойства -> отладка -> Аргументы команды.

В моем проекте это было пусто, и я добавил символ a, чтобы смоделировать вашу проблему.

Вот результат, который я получаю:

Щелкните правой кнопкой мыши проект -> Отладка -> Запустить новый экземпляр -> хотите ли вы его построить -> да

Выход:

Command-line argument count: 2
Arguments:
  argv[0]   <my macines path>\helpingStack1.exe
  argv[1]   a

Пожалуйста, проверьте это еще раз. Надеюсь, это поможет.

1) Я подозреваю, что ваши двоичные файлы не обновлены, когда вы запускаете этот скрипт, поэтому, пожалуйста, сделайте чистую сборку и убедитесь, что вы действительно используете тот же exe, что и тот, который вы собираете. Пожалуйста, проверьте конфигурацию - Debug/Release.

2) перейдите в папку, в которой вы создали проект, и щелкните правой кнопкой мыши папку проекта и измените свойство -> убедитесь, что флажок только для чтения не установлен.

person Ganesh Kamath - 'Code Frenzy'    schedule 26.12.2014
comment
Я создал новый проект, чтобы проверить, не вызвано ли это какими-то настройками проекта, но все равно не смог заставить его работать. a.pomf.se/zfzngu.webm - person codefox; 26.12.2014
comment
У меня отлично работает и в VS 2013. Проверьте, не мешает ли что-то еще, например, антивирусный сканер. - person Retired Ninja; 26.12.2014
comment
У меня нет ничего похожего на антивирусный сканер, работающий на моем компьютере для разработки. Ничего не должно мешать. - person codefox; 26.12.2014

Очевидно, что-то не так с IDE или проектом, или, может быть, с какой-либо другой настройкой только в вашей системе. Код идеален.

Вы пытались напрямую и независимо запустить свой выходной exe, выполнив его через командную строку ??

Запустите исполняемый файл с помощью командной строки, указав произвольные аргументы, и проверьте вывод.

person AneesAhmed777    schedule 26.12.2014
comment
Я попробовал оба, запустив его из IDE и командной строки. Результат тот же. Я, вероятно, попробую переустановить VS позже, хотя все остальное работает нормально. - person codefox; 26.12.2014
comment
Это странно..... Интересно, в чем может быть проблема..... Однако, в качестве слепого выстрела, я предлагаю попробовать другой компилятор, например. MinGW.... Удачи - person AneesAhmed777; 26.12.2014

стоит проверить свой набор символов в свойствах проекта-> Общие.

person GingerJack    schedule 26.12.2014
comment
Неважно, установил ли я его в Unicode или Multi-byte, в обоих случаях проблема остается. - person codefox; 26.12.2014