2017-05-05 74 views
0

在以下代碼:當將字符串傳遞給函數存儲

FILE * CMD = POPEN( 「的pidof -s GST-發射-0.10」, 「R」);

存儲在進程地址空間中的字符串「pidof -s gst-launch-0.10」在哪裏。我沒有看到它的堆棧..

添加整個代碼:

#include <stdio.h> 
#include <stdlib.h> 
#include <pthread.h> 
#include <fcntl.h> 
#include <string.h> 
#include <unistd.h> 

#define TRUE 1 
#define FALSE 0 

#define VS_STREAMER_ON  1 
#define VS_STREAMER_OFF  2 
#define VS_VIDSIG_ON  3 
#define VS_VIDSIG_OFF  4 
#define VS_VSIG_BL_OFF  5 


typedef int bool; 
bool bVidSignal, bVidSignalOld = FALSE; 
int iVidState = VS_STREAMER_OFF; 


bool IsStreamerRunning(); 

bool stopStreamer(); 
bool startStreamer(); 

bool ShowNoSignal() 
{ 
    printf("\nShowNoSignal()\n"); 

    system("dd if=/home/TDS/DiskOnChip/nosig.bmp of=/dev/fb0"); 

    return TRUE; 
} 


bool GetVideoSignal() 
{ 

    char buffer[10]; 

    memset(buffer, '\0', 10); 

    int fd = open("/sys/bus/i2c/devices/1-000f/sysstatus", O_RDONLY, 0); 
    //int fd = open("/sys/bus/i2c/drivers/tc358743_mipi/1-000f/sysstatus", O_RDONLY, 0); 

    if (fd > 0) 
    { 
     read(fd, buffer, sizeof(buffer)); 

     if (strlen(buffer) > 0) 
     { 
      long val = strtoul(buffer, NULL, 16); 

      close(fd); 

      if (val == 0x8F) 
      { 

       return TRUE; 
      } 
      else 
      { 

       return FALSE; 
      } 
     } 
    } 
    else 
    { 
     printf("GetVideoSignal(): can't open file\n"); 
    } 


    return FALSE; 

} 




void CheckVideoState(void) 
{ 
    //static int iRestartCnt = 0; 
    static int iAppCheckTic = 60;       // To Run for the first time 
    static int iVideoOn = FALSE; 
    static int iGstreamerStartCount = 0; 
    static int iGstreamerStartAttempt = 0; 
    static int iGstreamerStopCounter = 0; 

    bVidSignal = GetVideoSignal(); 

    if ((bVidSignal) && (bVidSignalOld)) 
    { 
     iVideoOn = TRUE; 
     printf("CheckVideoState() VideoOn=%d, MIPI_Status=%d, MIPI_Last_Status=%d\n",iVideoOn, bVidSignal, bVidSignalOld); 
    } 

    else if ((!bVidSignal) && (!bVidSignalOld)) 
    { 
     iVideoOn = FALSE; 
     printf("CheckVideoState() VideoOn=%d, MIPI_Status=%d, MIPI_Last_Status=%d\n",iVideoOn, bVidSignal, bVidSignalOld); 
    } 
    else 
    { 
     printf("CheckVideoState() VideoOn=%d, MIPI_Status=%d, MIPI_Last_Status=%d\n",iVideoOn, bVidSignal, bVidSignalOld); 
    } 
    bVidSignalOld = bVidSignal; 

    switch (iVidState) 
    { 
     case VS_STREAMER_OFF: 

      if (iVideoOn) 
      { 
       iGstreamerStartCount = 0; 
       iGstreamerStartAttempt = 0; 
       printf("CheckVideoState():VS_STREAMER_OFF: Signal ON\n"); 

     iVidState = VS_VIDSIG_ON; 
      } 
      else 
      { 
       iAppCheckTic++; 
       if (iAppCheckTic >= 60) 
       { 
        iAppCheckTic = 0; 
        iGstreamerStartCount = 0; 
        iGstreamerStartAttempt = 0; 
        if (IsStreamerRunning()) 
        { 
         printf("CheckVideoState():VS_STREAMER_OFF: Killing Gstreamer\n"); 
         stopStreamer(); 
         sleep(1); 
         ShowNoSignal(); 
        } 
       } 
      } 
      break; 


     case VS_VIDSIG_ON: 

      if (iGstreamerStartAttempt > 5) 
      { 
       printf("CheckVideoState():calling Reboot after 5 Gstreamer Restarts!\n"); 
       //SystemExit(SS_REBOOT); 
     system("reboot"); 
      } 

      if (iGstreamerStartCount == 0) 
      { 
       if (IsStreamerRunning()) 
       { 
        iGstreamerStopCounter = 0; 
        iVidState = VS_VIDSIG_OFF; 
        printf("CheckVideoState():VS_VIDSIG_ON: GStreamer Running Already Switch to VS_VIDSIG_OFF\n"); 
       } 
       else 
       { 
        startStreamer(); 
        printf("CheckVideoState():VS_VIDSIG_ON: Starting GStreamer\n"); 
        iGstreamerStartCount++; 
        iGstreamerStartAttempt++; 
       } 
      } 
      if (iGstreamerStartCount >= 10) 
      { 
       if (IsStreamerRunning()) 
       { 
        iVidState = VS_STREAMER_ON; 
        printf("CheckVideoState(): VS_VIDSIG_ON: GStreamer Running After %d Seconds, Switching to VS_STREAMER_ON\n", iGstreamerStartCount); 
       } 
     else 
       { 
        iGstreamerStartCount = 0; 
        printf("CheckVideoState(): VS_VIDSIG_ON: GStreamer Not Running After 5 Seconds, Clearing iGstreamerStartCount\n"); 
       } 
       break; 
      } 
      iGstreamerStartCount++; 
      break; 

     case VS_STREAMER_ON: 
      if (iVideoOn) 
      { 
       if (!IsStreamerRunning()) 
       { 
        iGstreamerStartCount = 0; 
        iGstreamerStartAttempt = 0; 
        printf("CheckVideoState():VS_STREAMER_ON: Gstreamer Not running even after video signal available\n"); 
       } 
      } 
     else 
      { 
       iVidState = VS_VIDSIG_OFF; 
       printf("CheckVideoState():VS_STREAMER_ON: Lost Video Signal\n"); 
       iGstreamerStopCounter = 0; 
      } 
      break; 

     case VS_VIDSIG_OFF: 

      if (IsStreamerRunning()) 
      { 
       stopStreamer(); 
       printf("CheckVideoState():VS_VIDSIG_OFF: Killing GStreamer\n"); 

      } 
      else 
      { 
       if (iGstreamerStopCounter >= 3) 
       { 
        iVidState = VS_STREAMER_OFF; 
        printf("CheckVideoState():VS_VIDSIG_OFF: Switching to VS_STREAMER_OFF after 3 seconds\n"); 
        break; 
       } 
      } 
      iGstreamerStopCounter++; 
      break; 
    } 
} 


pid_t GetStreamerPID() 
{ 
    pid_t pid = 0; 

    char line[100]; 

    memset(line, '\0', 100); 

    FILE *cmd = popen("pidof -s gst-launch-0.10", "r"); 

    if (cmd == NULL) 
    { 
    printf("Cmd Null\n"); 
    }  
    fgets(line, 100, cmd); 

    if (strlen(line) > 0) 
    { 
     pid = strtoul(line, NULL, 10); 
    } 

    pclose(cmd);  
    return pid; 
} 


bool IsStreamerRunning() 
{ 
    pid_t pid = GetStreamerPID(); 

    if (pid > 0) 
    { 
     return TRUE; 
    } 
    else 
    { 
     return FALSE; 
    } 
} 


void MainLoop() 
{ 
    while(1) 
    { 

     sleep(1);  
     CheckVideoState(); 

    } 

} 

bool startStreamer() 
{ 
    char command[256]; 

    pid_t pid = GetStreamerPID(); 

    if (pid > 0) 
    { 
    } 
    else 
    { 

     sprintf(command, "gst-launch imxv4l2src ! imxv4l2sink &"); 

     printf("StartStreamer: command=[%s]\n", command); 

     system(command); 
    } 
    return TRUE; 
} 

bool stopStreamer() 
{ 
    char command[256]; 

    pid_t pid = GetStreamerPID(); 

    if (pid > 0) 
    { 

     sprintf(command, "kill %d", pid); 

     printf("StopStreamer: command=[%s]\n", command); 

     system(command); 
    } 
    else 
    { 
    } 

    return TRUE; 

} 




int main() 
{ 

    MainLoop(); 
    return 0; 
} 

的代碼與分段故障崩潰和在IsStreamerRunning發生在CheckVideoState()案例VS_VIDSIG_ON()函數。 ..注意。這是隨機發生的。通過gdb進行調試,回溯停在popen上,它正在訪問不允許訪問的內存。因此分段錯誤。誰能幫我..

添加GDB回溯:

Breakpoint 1, 0x76ea6ffc in [email protected]@GLIBC_2.4() from /lib/libc.so.6 
#0 0x76ea6ffc in [email protected]@GLIBC_2.4() from /lib/libc.so.6 
#1 0x00010d14 in GetStreamerPID() at getPid.c:243 
#2 0x00010d98 in IsStreamerRunning() at getPid.c:263 
#3 0x00010aac in CheckVideoState() at getPid.c:157 
#4 0x00010dd4 in MainLoop() at getPid.c:284 
#5 0x00010efc in main() at getPid.c:358 

Program received signal SIGSEGV, Segmentation fault. 
0x80808080 in ??() 

(gdb) bt 
#0 0x80808080 in ??() 
#1 0x76ee1b70 in fork() from /lib/libc.so.6 
#2 0x76ea6d80 in [email protected]@GLIBC_2.4() from /lib/libc.so.6 
#3 0x76ea704c in [email protected]@GLIBC_2.4() from /lib/libc.so.6 
#4 0x00010d14 in GetStreamerPID() at getPid.c:243 
#5 0x00010d98 in IsStreamerRunning() at getPid.c:263 
#6 0x00010aac in CheckVideoState() at getPid.c:157 
#7 0x00010dd4 in MainLoop() at getPid.c:284 
#8 0x00010efc in main() at getPid.c:358 

我從過去一週的調試,使用的valgrind,GDB,我不知道爲什麼它會訪問地址從內存

+0

當你說*進程地址空間時,你指的是哪個進程?父母還是孩子? –

+0

而不是定義'line'並且隨後賦值,你可以在定義時初始化:'char line [100] = {0};'。 – pmg

+0

父...我正面臨一個奇怪的問題,這個功能..它是隨機拋出分段錯誤在popen ...任何人都可以猜測什麼可以是問題.. –

回答

0

字符串"pidof -s gst-launch-0.10""r"的內容都存儲在實現定義的區域中。通常將字符串文字放在代碼的「文本」區域中,或放在只讀的數據區域中。

在向函數傳遞參數的過程中堆棧上的內容是這些字符串文本的兩個地址,而不是它們的內容。這就是爲什麼你無法在你的進程堆棧空間中找到字符串的原因。

有關字符串文字在內存中放置的更多信息,請參閱this Q&A

+0

這些字符串必須不重疊?指向另一個字符串文字的中間是一種常見的編譯器優化。 –

+0

@JonathonReinhart你說得對,該標準允許實現爲字符串文字使用重疊內存。它是實現定義的。謝謝! – dasblinkenlight

+0

有沒有機會使用gdb查找/查找此字符串地址... –

0

POPEN是一個高層次的API,將執行以下操作(在POSIXplatformĺ:

  • 解析每殼語義您的字符串和構建「的argv」陣列
  • 爲標準輸入,標準輸出開口管是,新方法的標準錯誤
  • DUP2管到相應的文件描述符
  • Exec的新過程

因此,您的字符串本身不會出現在新的進程地址空間中。它的組成部分將出現在通過的argv中。