当将字符串传递给函数存储

当将字符串传递给函数存储

问题描述:

在以下代码:当将字符串传递给函数存储

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 ...任何人都可以猜测什么可以是问题.. –

字符串"pidof -s gst-launch-0.10""r"的内容都存储在实现定义的区域中。通常将字符串文字放在代码的“文本”区域中,或放在只读的数据区域中。

在向函数传递参数的过程中堆栈上的内容是这些字符串文本的两个地址,而不是它们的内容。这就是为什么你无法在你的进程堆栈空间中找到字符串的原因。

有关字符串文字在内存中放置的更多信息,请参阅this Q&A

+0

这些字符串必须不重叠?指向另一个字符串文字的中间是一种常见的编译器优化。 –

+0

@JonathonReinhart你说得对,该标准允许实现为字符串文字使用重叠内存。它是实现定义的。谢谢! – dasblinkenlight

+0

有没有机会使用gdb查找/查找此字符串地址... –

POPEN是一个高层次的API,将执行以下操作(在POSIXplatformĺ:

  • 解析每壳语义您的字符串和构建“的argv”阵列
  • 为标准输入,标准输出开口管是,新方法的标准错误
  • DUP2管到相应的文件描述符
  • Exec的新过程

因此,您的字符串本身不会出现在新的进程地址空间中。它的组成部分将出现在通过的argv中。