#include "stdio.h"
int main(int argc, char *argv[])
{
int x = 1;
printf("%d %d %d\n", ++x, x, x++);
return 0;
}
You're running into two issues:
1. Undefined behavior -- you are attempting to modify the value of an
object more than once between sequence points, and the Standard imposes
no requirement on how to handle that behavior. Basically, any
expression of the forms:
i = i++;
j = k++ * k++;
foo(i,i++,--i);
invoke undefined behavior. Read up on the semantics of the "++" and
"--" operators in an *authoritative* reference (the Standard would
obviously be one, but also K&R2 or H&S5); they don't work the
way most
people think they should.
2. Order of evaluation -- AFAIK, there's no requirement that
expressions in a function parameter list be evaluated in any particular
order. At first blush, it *looks* like the arguments were evaluated
from right to left (if x = 1, then x++ evaluates to 1, with the side
effect that x == 2, and ++x evaluates to 3, with the side effect that x
== 3), but given that you've invoked undefined behavior the actual
reason may be something else entirely.
$ gcc -Wall cc_test.c
cc_test.c: In function ‘main’:
cc_test.c:6: warning: operation on ‘x’ may be undefined
cc_test.c:6: warning: operation on ‘x’ may be undefined
이런 경고가 발생한다.
분명 x는 변수인데, 그에 대한 operation이 정의되지 않았다는게 무슨 말인지 모르겠지만,
아무튼 실행을 하면
$ ./a.out
3 3 1
요런 희한한 결과가 나온다.
아무튼, calling convention과도 연관이 있어 보이는데,
c언어 특성상 right-left 로 push 하므로(가장 위에는 왼쪽 값이 오도록)
가장 먼저들어가는, 오른쪽 x++ 은 1이 들어가고
1을 더해준다음, 다음 명령어를 수행하면서(++x) 한번에 2가 증가하게 되고
그럼으로 인해 x, ++x 순으로 3이 들어가는게 아닐까 생각된다.
VLC 에는 web interface 라는 넘이 있는데,
이녀석을 원격지에서 http query를 통해 제어가 가능하다.
윈도우에서 기본설치시
C:\Program Files\VideoLAN\VLC\http\requests 경로에 존재하는 파일을 읽어보면 될 듯 하다.
웹에서 접속시에는
http://localhost:8080/requests/filename.xml?query
식으로 하면된다.
아래는 readme.txt 파일
$Id$
This file describes commands available through the requests/ file:
Lines starting with < describe what the page sends back
Lines starting with > describe what you can send to the page
All parameters need to be URL encoded.
Examples:
# -> %23
% -> %25
+ -> %2B
space -> +
...
status.xml:
===========
< Get VLC status information, current item info and meta.
> add <mrl> to playlist and start playback:
?command=in_play&input=<mrl>
> add <mrl> to playlist:
?command=in_enqueue&input=<mrl>
> play playlist item <id>:
?command=pl_play&id=<id>
> toggle pause. If current state was 'stop', play item <id>:
?command=pl_pause&id=<id>
> stop playback:
?command=pl_stop
> jump to next item:
?command=pl_next
> jump to previous item:
?command=pl_previous
> delete item <id> from playlist:
?command=pl_delete&id=<id>
> empty playlist:
?command=pl_empty
> sort playlist using sort mode <val> and order <id>:
?command=pl_sort&id=<id>&val=<val>
If id=0 then items will be sorted in normal order, if id=1 they will be
sorted in reverse order
A non exhaustive list of sort modes:
0 Id
1 Name
3 Author
5 Random
7 Track number
> toggle random playback:
?command=pl_random
> toggle loop:
?command=pl_loop
> toggle repeat:
?command=pl_repeat
> toggle enable service discovery module <val>:
?command=pl_sd&val=<val>
Typical values are:
sap
shoutcast
podcast
hal
> toggle fullscreen:
?command=fullscreen
> set volume level to <val> (can be absolute integer, percent or +/- relative value):
?command=volume&val=<val>
Allowed values are of the form:
+<int>, -<int>, <int> or <int>%
> seek to <val>:
?command=seek&val=<val>
Allowed values are of the form:
[+ or -][<int><H or h>:][<int><M or m or '>:][<int><nothing or S or s or ">]
or [+ or -]<int>%
(value between [ ] are optional, value between < > are mandatory)
examples:
1000 -> seek to the 1000th second
+1H:2M -> seek 1 hour and 2 minutes forward
-10% -> seek 10% back
playlist.xml:
=============
< get the full playlist tree
browse.xml:
===========
< ?dir=<dir>
> get <dir>'s filelist
vlm.xml:
========
< get the full list of VLM elements
vlm_cmd.xml:
============ < execute VLM command <cmd> ?command=<cmd> > get the error message from <cmd>
예전글인 이녀석 2008/12/22 - [Linux] - 심볼릭 링크에 대한 미스테리
왜 심볼릭 링크의 크기는 파일크기와 문자열 길이가 동일할까? 라는 의문이 들었는데,
not null-terminated 라고 함은, inode 쪽에서 filename 변수를 가지고,
실제로 filename 변수에는 \0(=NULL)이 없기 때문이 아닐까 싶다.
i-node에는 파일의 속성이 저장되고,
디렉토리 구조체에 파일의 i-node와 파일의 이름이 저장된다.
# vi /usr/include/bits/dirent.h
struct dirent
{
#ifndef __USE_FILE_OFFSET64
__ino_t d_ino;
__off_t d_off;
#else
__ino64_t d_ino;
__off64_t d_off;
#endif
unsigned short int d_reclen;
unsigned char d_type;
char d_name[256]; /* We must not include limits.h! */
};
# vi /usr/include/bits/stat.h
struct stat
{
__dev_t st_dev; /* Device. */
unsigned short int __pad1;
#ifndef __USE_FILE_OFFSET64
__ino_t st_ino; /* File serial number. */
#else
__ino_t __st_ino; /* 32bit file serial number. */
#endif
__mode_t st_mode; /* File mode. */
__nlink_t st_nlink; /* Link count. */
__uid_t st_uid; /* User ID of the file's owner. */
__gid_t st_gid; /* Group ID of the file's group.*/
__dev_t st_rdev; /* Device number, if device. */
unsigned short int __pad2;
#ifndef __USE_FILE_OFFSET64
__off_t st_size; /* Size of file, in bytes. */
#else
__off64_t st_size; /* Size of file, in bytes. */
#endif
__blksize_t st_blksize; /* Optimal block size for I/O. */
#ifndef __USE_FILE_OFFSET64
__blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */
#else
__blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */
#endif
#ifdef __USE_MISC
/* Nanosecond resolution timestamps are stored in a format
equivalent to 'struct timespec'. This is the type used
whenever possible but the Unix namespace rules do not allow the
identifier 'timespec' to appear in the header.
Therefore we have to handle the use of this header in strictly
standard-compliant sources special. */
struct timespec st_atim; /* Time of last access. */
struct timespec st_mtim; /* Time of last modification. */
struct timespec st_ctim; /* Time of last status change. */
# define st_atime st_atim.tv_sec /* Backward compatibility. */
# define st_mtime st_mtim.tv_sec
# define st_ctime st_ctim.tv_sec
#else
__time_t st_atime; /* Time of last access. */
unsigned long int st_atimensec; /* Nscecs of last access. */
__time_t st_mtime; /* Time of last modification. */
unsigned long int st_mtimensec; /* Nsecs of last modification. */
__time_t st_ctime; /* Time of last status change. */
unsigned long int st_ctimensec; /* Nsecs of last status change. */
#endif
#ifndef __USE_FILE_OFFSET64
unsigned long int __unused4;
unsigned long int __unused5;
#else
__ino64_t st_ino; /* File serial number. */
#endif
};
다르게 생각해 보자면,
directory table에 파일 이름이 저장되고, (심볼릭 링크)
속성으로 심볼릭 링크가 지정되며,
inode의 filesize는 string이 아닌 data로서 \0(=NULL)이 빠진 순수한 원본 경로만 들어가서
ls 시의 심볼릭 링크 파일의 크기가 예상과 달리 -1 크기로 나오는게 아닐까 싶다.
Return Value
Upon successful completion, readlink() shall return the count of bytes placed in the buffer. Otherwise, it shall return a value of -1, leave the buffer unchanged, and set errno to indicate the error.
The readlink function gets the value of the symbolic link filename. The file name that the link points to is copied into buffer. This file name string is not null-terminated; readlink normally returns the number of characters copied. The size argument specifies the maximum number of characters to copy, usually the allocation size of buffer.
APPLICATION USAGE
Conforming applications should not assume that the returned contents of the symbolic link are null-terminated.
RATIONALE
Since IEEE Std 1003.1-2001 does not require any association of file times with symbolic links, there is no requirement that file times be updated by readlink(). The type associated with bufsiz is a size_t in order to be consistent with both the ISO C standard and the definition of read(). The behavior specified for readlink() when bufsiz is zero represents historical practice. For this case, the standard developers considered a change whereby readlink() would return the number of non-null bytes contained in the symbolic link with the buffer buf remaining unchanged; however, since the stat structure member st_size value can be used to determine the size of buffer necessary to contain the contents of the symbolic link as returned by readlink(), this proposal was rejected, and the historical practice retained.
원인은 못찾았지만, 커널 옵션에서 quiet 주어도 나오길래, 최소한 커널 오류는 아닌것으로 판단
busybox에서 찾아보니
./shell/ash.c:4849: ash_msg_and_raise_error("cannot open %s: %s", fname, errmsg(errno, "no such file"));
한녀석이 걸려 나온다.
특이한건, 이 소스가 있는 부분은 openredirect라는 함수.
음.. 머하는 녀석일려나?
static int
openredirect(union node *redir)
{
char *fname;
int f;
switch (redir->nfile.type) {
case NFROM:
fname = redir->nfile.expfname;
f = open(fname, O_RDONLY);
if (f < 0)
goto eopen;
break;
case NFROMTO:
fname = redir->nfile.expfname;
f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666);
if (f < 0)
goto ecreate;
break;
case NTO:
/* Take care of noclobber mode. */
if (Cflag) {
fname = redir->nfile.expfname;
f = noclobberopen(fname);
if (f < 0)
goto ecreate;
break;
}
/* FALLTHROUGH */
case NCLOBBER:
fname = redir->nfile.expfname;
f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
if (f < 0)
goto ecreate;
break;
case NAPPEND:
fname = redir->nfile.expfname;
f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
if (f < 0)
goto ecreate;
break;
default:
#if DEBUG
abort();
#endif
/* Fall through to eliminate warning. */
case NTOFD:
case NFROMFD:
f = -1;
break;
case NHERE:
case NXHERE:
f = openhere(redir);
break;
}
return f;
ecreate:
ash_msg_and_raise_error("cannot create %s: %s", fname, errmsg(errno, "nonexistent directory"));
eopen:
ash_msg_and_raise_error("cannot open %s: %s", fname, errmsg(errno, "no such file"));
}
2010.04.21 추가
inittab에 ttyAS1을 초기화 하는 부분이 있었는데, 커널에서(?) 사용하지 않도록 해놔서 계속 에러가 난 모양이다.
아무튼, /bin/sh에 ttyAS1을 열도록 해놓았기 때문에, busybox에서 ash이 sh을 대체하고,
그러다 보니 ash에서 에러발생. 머.. 문제 해결 끝!
$ cat target/etc/inittab # Example Busybox inittab ::sysinit:/etc/init.d/rcS ttyAS0::askfirst:/bin/sh ttyAS1::askfirst:/bin/sh ::ctrlaltdel:/sbin/reboot ::shutdown:/sbin/swapoff -a ::shutdown:/bin/umount -a -r ::restart:/sbin/init
그리고 iconv() 함수는
문자열 변수들은 2중 포인터로 넘겨주고(왜?) inbytesleft는 strlen(*inbuf) 의 값을 outbytesleft는 strlen(*outbuf) 의 값을 넣어주면된다.
물론 변환에 따라서, 길이가 가변적으로 달라질수 있기 때문에 주의해야 한다.
만약, 변환중 메모리가 넘치게 되면 EILSEQ 에러가 발생하게 되며, (물론 넘치기 전에 데이터는 빼낼수 있다.)
변수의 포인터가 2중 포인터가 아니면 "__gconv: Assertion `outbuf != ((void *)0) && *outbuf != ((void *)0)' failed."
이런 에러를 만나게 될 것이다.