2016-02-21 2 views
1

У меня есть этот код для проверки функции Ackermann, я называю это программой P1. В ackerman (int m, int n). Моя цель: если OUT не был определен, программа запустится и просто распечатает результат после его завершения. Если OUT определен, программа будет печатать «xxx» каждый «цикл» и ждать ввода char из stdin. У меня есть внешний процесс для чтения вывода P1, поймать строку «xxx» (чтобы что-то сделать) и записать символ char в P1, чтобы он мог продолжить. , если я компилирую без определения OUT и запускаю P1 автономно, код может выполняться полностью и распечатать ack (3,6) = SomeValue, но если я включу OUT и запустил внешний процесс с P1, P1 может получить символ какое-то время, и «пауза» внезапно, никакой аварии, ошибки, выхода. Я использовал переменную c для подсчета времени до остановки P1, это не фиксированное число (3813, 3951, 3804, ....). Внешний процесс вызывается в C#, и был протестирован очень хорошо. Я использовал его для многих случаев, но в этой функции ackermann его остановили. Почему это не останавливается в первом цикле, но в довольно большом числе циклов? Есть ли связь между печатью с остановкой?Запуск программы на C++ (замораживание, без ошибок, без выхода) после нескольких распечаток (cout)

P1:

int MAX = 99999; 
class stack { 
private: 
    int num[99999]; 
    int size; 
public: 
    stack() { 
     size = 0; 
    } 
    void push(long x) { 
     if(size < MAX) 
      num[++size] = x; 
     else { 
      cout<<"Full Stack"<<endl; 
      return; 
     } 
    } 
    int pop() { 
     if(size==0) { 
      cout<<"Out of stack memory"<<endl; 
      return -1; 
     } 
     return num[size--]; 
    } 
    bool isEmpty() { 
     if(size == 0) 
      return true; 
     else 
      return false; 
    } 
}; 

int ackman(int m,int n) 
{ 
    stack v; 
    v.push(m); 
    int c = 0; 
    while(!v.isEmpty()) { 
     m = v.pop(); 
     if(m==0 ||n==0) 
      n+= m+1; 
     else { 
      v.push(--m); 
      v.push(++m); 
      n--; 
     } 
     c++; 

#ifdef OUT 
     printf("c is %d\n",c); 
     cout << endl; 
     //flush(stdin); 
     //flush(stdout); 
     cout << "xxx" << endl; 
     getchar(); 
     //sleep(200); 
#endif 
    } 
    return n; 
} 

void ack() 
{ 
    int m = 3, n = 6; 
#ifdef DEMO 
    m = 3; 
    n = 4; 
#endif 
    try{ 
     int k = ackman(m,n); 
     printf("Ack %d , %d = %d\n",m,n,k); 
    }catch(...){ 
     cout << "Co loi khi ack"; 
    } 
} 

//just example 
int main(){ 
ack(); 
return 0; 
} 


Внешний процесс

static List<BenchMemory> benchMemory(String exeName, String caseName) 
      { 
       int count = 0; 
       Console.Title = "Bench memory: " + exeName + " case: "+caseName; 
       Console.WriteLine("Exe: {0}, case: {1}", exeName, caseName); 
       using (Process process = new Process()) 
       { 
        /* Create the start info object */ 
        ProcessStartInfo startInfo = new ProcessStartInfo(); 
        startInfo.FileName = exeName + ".exe"; 
        startInfo.Arguments = caseName; 
        startInfo.UseShellExecute = false; 
        startInfo.RedirectStandardOutput = true; 
        startInfo.RedirectStandardInput = true; 
        List<BenchMemory> listMemResult = new List<BenchMemory>(); 
        #region handler 
        DataReceivedEventHandler outDataHandler = (object sender, DataReceivedEventArgs e) => 
        { 
         if (e.Data != null) 
         { 
          count++; 
          Console.WriteLine(e.Data); 
          if (!process.HasExited && e.Data != null && e.Data.ToLower().Equals("xxx")) 
          { 
           var bMem = getProcessMemory(process, exeName, caseName); 
           listMemResult.Add(bMem); 
           process.StandardInput.WriteLine("k"); 
          } 


         } 
        }; 
        #endregion 
        process.StartInfo = startInfo; 
        process.OutputDataReceived += outDataHandler; 
        process.Start(); 
        process.BeginOutputReadLine(); 
        process.WaitForExit(); 
        var topPeak = listMemResult.Take(10).ToList(); 
        process.Refresh(); 
        return topPeak; 
       } 
      } 
+0

Вы используете C# или C++? Разные языки. –

+0

Когда вы использовали отладчик и один шаг через вашу программу, какой оператор вызывает проблему? –

+0

@ThomasMatthews, P1 - это C++, внешний процесс - C#, это немного раздражает. Но они оба - консольное приложение. Причина, по которой программа останавливается на большом количестве итераций, я использую метод распечатки, чтобы найти проблемную строку. Программа запускается много раундов с «c is k», «c is k», ... и останавливается после печати «c is». Кажется, что P1 больше не может получать контент из внешнего процесса и останавливается, потому что getchar(). Я вызываю P1 внутри внешнего процесса, поэтому я не могу вручную нажимать клавишу, чтобы передать getchar().Я думаю, это потому, что я использую фиксированный массив для Stack, какой-то предел массива – Andiana

ответ

3

Добавление fflush(stdin); в программе ++ должен сделать трюк (фрагмент измененного кода сильфона) Вашего C:

#ifdef OUT 
     printf("c is %d\n",c); 
     cout << endl; 
     cout << "xxx" << endl; 
     fflush(stdin); // note 
     getchar(); 
#endif 

Для целей отладки я также немного исправил C# код, но ничего не стоит смотреть:

DataReceivedEventHandler outDataHandler = (object sender, DataReceivedEventArgs e) => 
{ 
    if (e.Data != null) 
    { 
     var senderProcess = sender as Process; 

     if(sender == null) 
      Console.Write("Sender == NULL?"); 

     if(senderProcess.HasExited) 
      Console.WriteLine("Exited"); 

     count++; 
     Console.WriteLine(e.Data); 

     // e.Data != null redundant check, already everything wrapped in if(e.Data != null) 
     if (e.Data.Trim().ToLower().Equals("xxx")) 
     { 
      senderProcess.StandardInput.Write("k"); 
      Console.WriteLine("Pass"); 
     } 
    } 
}; 

Числа меня в моем случае всегда 2047 был в первый раз, после замены WriteLine с Write (WriteLine печати два символа, обратите внимание на \n), я добрался до 4095. Сила 2 снова (добавьте +1)? Буфер? При проверке с помощью отладчика StandardOutput вы заметите, что в выходном буфере действительно 4096 символов. Кроме того, если установить точку останова на Write, вы заметите, что после 4095 она застрянет там (используйте условные точки останова, чтобы облегчить вам жизнь) и никогда не доходите до Console.WriteLine("Pass").

StandardOutput.Flush не решила проблему (также не удалось найти в документации), а также getchar не очищает ее, если я правильно помню.

Добавление fflush(stdin) в программу на C++ очищает его, создавая пространство для C#, чтобы продолжить запись в нем.